GNU arch Book

Archive:   tez@kamihira.com--2004-private

Version:   Book--GNU-arch--0.0.1

Revision:   patch-52

2004-05-11 16:24(JST)


目次

序文
この本の読み方
この本での約束ごと
印刷上の規約
アイコン
この本の構成
この本はGFDLだ
謝辞
1. 導入
バックアップ
テキストファイルとバイナリファイル
差分と複数のファイル
協力者たち
分岐、そしてマージ
ブルーな日々
GNU arch
2. インストール
インストール
最初にやらなくてはならないこと
UserIDの設定
アーカイブの作成
デフォルトアーカイブの設定
三つの困難
この章のまとめ
3. バージョンの作成
前提となる環境
バージョンとは何か
初期データのインポート
概論
利用するサンプルプログラム
初期インポート作業(1) - tla init-tree
初期インポート作業(2) - tla id-tagging-method
初期インポート作業(3) - インポートファイルの確認
初期インポート作業(4) - インポート
リビジョンとは何か
プロジェクトツリーとは何か
日々の利用
概論
tla changes(1)
undo と redo
修正のコミット
プリスティン・コピー
よくあるトラブル
プロジェクトツリー中に恐ろしい名前のファイルができた
コミットに失敗する
この章のまとめ
4. インベントリ
=tagging-method
第一のチェック - ファイルタイプチェック
第二のチェック - インベントリチェック
チェックの詳細
tla inventory
tla tree-lint
既存プロジェクトの移行
explicit による方法
tagline による方法
この章のまとめ
5. ブランチとマージ
ブランチ(分岐)
アーカイブの公開
マージの技法
tla replay
tla update
tla star-merge
パッチログの限界
マージの失敗が意味すること
6. 最適化
リビジョンキャッシュ
アーカイブ・ミラー
リビジョンライブラリ
リビジョンの検索順序
7. 新しい概念
インベントリ
チェンジセット
パッチログ
継続
8. サインつきアーカイブ
チェックサムの計算
サインつきアーカイブ
サインつきアーカイブのチェック
デフォルトルールの設定
9. フックとレシピ集
フック
レシピ集
私の過去を返して!
プロジェクトツリーにいながらにして分岐したい
オフラインで分岐を作ってそちらにスイッチしたい
いまいるプロジェクトツリーの内容を tar ファイルに固めたい
いまいるプロジェクトツリーの中のソースファイルを grep し たい
10. マルチツリープロジェクト
概要
GNU arch internal
カスタマイズの方法
A. 名前規約と各種ファイル形式
名前規約
User ID と UID
アーカイブ名
カテゴリ名とブランチ名
バージョン名
パッチレベル名
各種ファイル形式
チェンジセット
インベントリマップ
ディレクトリメタデータ
削除ファイル、追加ファイル
パッチファイル
{arch}管理領域
アーカイブ領域
ライブラリ領域
.arch-params
各種一時ファイル
UUID(GUID)
プレシャス、バックアップ、ジャンクの具体的な意味
プレシャス属性
バックアップ属性とジャンク属性
トランザクション
特殊なリビジョンと状態遷移
B. GNU arch関連情報
ツール
リンク集
C. GNU arch コマンドリファレンス
リファレンスの見方
tla サブコマンド
ヘルプコマンド
ユーザコマンド
tla my-id
プロジェクトツリーコマンド
tla init-tree
tla tree-root
tla tree-version
tla set-tree-version
tla undo
tla redo
tla changes
tla file-diffs
プロジェクトツリーインベントリコマンド
tla inventory
tla tree-lint
tla id
tla id-tagging-method
tla add-id
tla delete-id
tla move-id
tla mv
tla explicit-default
tla id-tagging-defaults
パッチセットコマンド
tla changeset
tla apply-changeset
tla show-changeset
アーカイブトランザクションコマンド
tla make-archive
tla archive-setup
tla make-category
tla make-branch
tla make-version
tla import
tla commit
tla get
tla get-changeset
tla lock-revision
tla archive-mirror
アーカイブコマンド
tla abrowse
tla rbrowse
tla categories
tla branches
tla versions
tla revisions
tla ancestry
tla ancestry-graph
tla cat-archive-log
tla cacherev
tla cachedrevs
tla uncacherev
tla archive-meta-info
tla archive-snapshot
tla archive-version
tla archive-fixup
パッチログコマンド
tla make-log
tla log-versions
tla add-log-version
tla remove-log-version
tla logs
tla cat-log
tla changelog
tla log-for-merge
tla merges
tla new-merges
マルチプロジェクト設定用コマンド
tla build-config
tla cat-config
ブランチとマージに関するコマンド
tla tag
tla update
tla replay
tla star-merge
tla apply-delta
tla missing
tla join-branch
tla sync-tree
tla delta
ローカルキャッシュ関連コマンド
tla changes
tla file-diffs
tla file-find
tla pristines
tla lock-pristine
tla add-pristine
tla find-pristine
リビジョンライブラリコマンド
tla my-revision-library
tla library-config
tla library-find
tla library-add
tla library-remove
tla library-archives
tla library-categories
tla library-branches
tla library-versions
tla library-revisions
tla library-log
tla library-file
公開用リビジョンコマンド
tla grab
スクリプト支援コマンド
tla parse-package-name
tla valid-package-name
D. Copyright

図目次

1.1. image.tiff の縄文式バージョン管理
1.2. 一般的なファイルの縄文式バージョン管理
1.3. 一列に並んだリビジョン
1.4. GNUdiff の処理イメージ
1.5. GNUpatch の処理イメージ
1.6. 隣り合うリビジョン間への GNUdiffの実行
1.7. 最初のリビジョンと差分の集まりだけを残したところ
1.8. GNUpatchによる各リビジョンの復元
1.9. 差分の集まりをひとつのファイルにまとめた様子
1.10. CVSに依頼して作ったふたつの作業コピー
1.11. 評価版 = 製品版 + タイマー
1.12. リポジトリ内に一列に並んだリビジョン
1.13. 分岐後のリポジトリの様子
1.14. 修正点の選択的なとりこみ
1.15. コンピュータといろいろなサービス
1.16. コンピュータとアクセス制限
1.17. CVS サービス専用機とアクセス制限
1.18. CVS サービス専用機と子会社からのアクセス
1.19. CVS の分岐の限界
1.20. GNU arch の分岐はリポジトリの境界を越えることができる
3.1. まちがったバージョンの階層構造
3.2. 正しいバージョンの階層構造
3.3. バージョン同士の関係
3.4. プロジェクトツリーとアーカイブ
3.5. base-0, base-0 への修正を加えたツリー、,,undo-1 の間の関 係
A.1. コミットのオプションと状態遷移

表目次

5.1. 登場人物
9.1. フックイベント一覧
9.2. 設定される環境変数一覧
A.1. ファイル一覧
A.2. ファイル一覧
A.3. ファイル一覧
A.4. ファイル一覧
A.5. ファイル一覧
C.1. idタグづけの方法
C.2. replay時に残されるファイル
C.3. 終了ステータスの意味

序文

GNU arch は バージョン管理システムと よばれるプログラムの一つであり、既存のバージョン管理システム のい くつかのアイディアを更に発展させようとして Tom Lord によって2000年 の初頭から開発されてきたものだ。改良点についての詳細はこの本の内容 を超えているが、最も重要な特徴は、分散型のシステム構成をとっている ことと、チェンジセットと呼ばれるデータを中心とした設計になっている ところだ。

この本の読み方

この本はたった 3 種類の人たちに向けて書かれたものだ。

コンピュータには詳しくないが、バージョン管理システムに興 味がある人

あなたには第1章が役には立た つと思う。もしこの章を理解できないとすれば、それは私の書き方が 悪いからだ。誰も信じてはくれないが、私にとってはこの章が一番重 要な章だ。

Windows を通常利用している

非 常に残念なことに、現時点では GNU arch は Windows 上ではまだ動作 しない。詳しい動向を追ってはいないが、移植を進めているチームがあ ると聞いている。第1章のギャグにつき合ってくれるだけで許してほし い。GNU arch の理解度には限りがあるが、ギャグの改良には終りはな い。

Unixのコマンドを利用できる

(XXX)

ハッカー

こんな本の程度の内容 なんてすべて知っている、などと言わないでほしい。この本の中にある 間違いや、改良点について示唆していただけると非常に助かる。

この本での約束ごと

ここではこの本で利用されるさまざまな規約について触れる

印刷上の規約

固定幅

コマンド、コマンド出力、スイッチに利用する

イタリックな固定幅

プログラムやテキスト中で置き換え可能なアイテムに対し て利用する

イタリック

ファイルやディレクトリの名前に利用する

アイコン

注意

このアイコンは周りにあるテキストに関連した注意を示す。

ティップ

このアイコンは周りにあるテキストに関連したヘルプ情報を示 す。

警告

このアイコンは回りにあるテキストに関連した警告を示す。

ソースコードのサンプルは、単なる一例にすぎない。普通のやり方 で利用できるとは思うが、問題点を簡単に示すためのものであり、良 いプログラミングスタイルの例として載せたものではない。

この本の構成

以下の章とその内容をここで一覧にしておく:

第 1 章, 導入

バージョン管理システムの一般論、GNU arch が生まれた 背景、その特徴について

第 2 章, インストール

説明を始めるに当たって GNU arch を実際にインストール してみる

第 3 章, 基本的な使い方

他アーカイブとのやりとりを含まない範囲での日常的な利 用方法に沿った説明をする。データのインポート、取得し、修正し、コミット などについて触れる。

第 4 章, 既存プロジェクトの移行

主に既存プロジェクト移行時によく問題になるファイル認 識規則についての説明

第 5 章, マージとブランチ

マージとブランチについての説明。他アーカイブとのやり とりをする必要がある場合にはこの章の理解が必要になる。GNU arch に特化 した内容が多く、分散バージョン管理という観点からは最も重要な章かも知れ ない。

第 6 章, XXX

第 7 章, YYY

第 8 章, ZZZ

第 9 章, WWW

Appendix A, AAA

Appendix B, BBB

Appendix C, コマンドリファレンス

GNU arch コマンドごとにその機能を詳細にのべた。一度全体を理解した後は、 この部分が一番重要になるだろう。

この本はGFDLだ

この本は、The GNU Free Documentation License にしたがう。こ のライセンスは、文中に "Free" という言葉が含まれているにもかかわら ず、Free ではない、と考える人々がいる。私はその区別ができるほど、 この問題についていまだ深く考えたことがないが、六法全書をすべて読破 する前に日本国の法律に従うように、この GFDL なるものに従おうと思う。 詳しくはコピーライトの章を参照してほしい。

この本の比較的最近のバージョンは、http://arch.bluegate.org/gab-jp/book.htmlに ある。またこの本自体はもちろん GNU arch で管理されている。最新の FQDN は、補遺を参照してほしい。

謝辞

… そしてGNU arch コミュニティーの人々。

第1章 導入

コンピュータに一度でも触ったことのある人なら、長く保存してお きたいようなデータを誰でもひとつくらいは持っているものだ。それは大 切な人からの E-mail に添付されていたデジカメでとった写真だったり、 上司ににらまれながら徹夜で仕上げた提案書だったり、カナダの天才ピア ニストが演奏したバッハの変奏曲だったり、hello world とだけ画面に表 示される、本人以外にとっては何の意味もない C 言語のソースコードだっ たり、今日習いにいったおかし教室の先生が自分にだけこっそり教えてく れたチーズケーキのレシピだったり、過去10年分の株価チャートだったり、 次のペットはコッカースパニエルにすべきか、チワワにすべきかについて の非常に論理的な知人からの忠告のメールだったり、2週間ホテルに缶詰 になって書き上げた恋愛小説の最後のたった一言だったりする。これらす べてが、すべて1と0の組み合わせ、つまりデジタルデータとして表現し保 存できることは、実は鉄の塊が空を飛ぶことや、5光年も離れた星が肉眼 で見えるほどに宇宙が澄みきっているのと同じくらい驚嘆すべきことなの だが、たいていの人はそれに気づいてはいない。

このようなデジタルデータは、おおきく二つのグループにわけるこ とができる。ひとつは、一度保存したら二度とその内容がかわらないもの。 もうひとつは、時間と共に修正や改良が必要であり、内容が変化していく ものだ。大切な人の写真はどうだろう? 普通は前者だろう。送ってもらっ た写真を画像編集ソフトで勝手に修正したりしちゃいけない。ありのまま の彼女の姿をありのまま受け入れよう。そうすれば君はずっと彼女の友人 でいられる。でももしかすると君は雑誌の編集者かなんかで、その写真は 一ヵ月に 15 万部も売れる雑誌の一面をかざるはずのコラージュの素材に なるのかも知れない。なら話しは別だ。その画像には大いに修正が入る。 君は背景を黒く塗りつぶし、右目の上にどっかの国の大統領の左目を張り 付け、別に作っておいたレンガのハッチパターンで塗りつぶしたバルテノ ン神殿の裏口に、そのピカソの首を転がす必要がある。それを上司に確認 してもらって、何度か修正を入れる。やっぱり元のやつがいい、とか言わ れてもいいように、修正してできた版ごとに名前のついたファイルにバッ クアップをとっておこう。こうして君の作品は採用され、雑誌は晴れて発 売され、その夜君はどっかのラウンジで静かに酒を飲みながらこれで一段 落だと一人ごちる。

時間と共に内容に変更や修正が加わるデータを履歴つきで時間にそっ て管理したいという場面はよくある。しかもそれは具体的なデータの種類 によらない、一般的な話だってことがわかる。上のような画像であれ、編 集中の音楽であれ、プログラムのソースコードであれ、ドキュメントであ れ、いつ誰がどのような変更をどこに、どのように加えたかを即座に知る ことができて、間違った時のために過去のどの時点のデータにもすぐに戻 れる。そんな汎用的な仕組みがあれば、これは便利だ。こんな発想から発 達してきた、ソフトウェアの一分野がある。バージョン管理シ ステムがそれだ。ここで説明しようとしている GNU arch と いうソフトウェアも、このジャンルに分類されるソフトウェアだ。気づい ただろうか。いま私はこっそり、「いつ誰がどのように」と書いた。そう、 写真の例は一人でやる作業のシナリオだったが、もっと一般的に複数の人 間がひとつのデータをめぐって共同作業するようなケースまで含めて考え てみたいのだ。

実はバージョン管理システムと呼ばれるソフトウェアはすでにいく つも存在している。商用のものもあれば、フリーソフトウェアのものもあ る。フリーソフトウェアの側で一番有名なのは、CVS と呼ばれるもので、 事実上その分野の標準になっている。GNU arch が作られたのは CVS より もずっと後のことだが、こちらもフリーソフトウェアなので、ある一定の ルールを守れば、誰でも自由に利用することができる。ところで人生には 同じ冗談を二度言ってはいけない、という鉄則があるのをご存じだろうか? これに従えば CVS というソフトがあるのに、あえて別のソフトを作った のには、もちろんちゃんとしたわけがある。結局、同じ車輪を二度まわす ほど暇な人間はそう多くはない。この章では、GNU arch の生い立ちにつ いて説明しようと思が、それにはまず、バージョン管理システムの歴史に ついて説明する必要があるし、その歴史のなかで CVS がどんな風に生ま れてきたかも説明する必要があるし、それを踏まえた上でその欠点も説明 する必要がある。それではじめて、どうしてGNU arch が生まれたかもわ かってもらえるというものだ。

もし君がプログラムについての知識がゼロだったり、Unix という 言葉を知らなかったり、知っていても使ったことはないのなら、後の章は まったくのチンプンカンプンであること請け合いだが、この章だけは退屈 せずに読んでもらえることを目指したつもりだ。そんな風にしたのにはわ けがある。実はバージョン管理システムの歴史は、フリーソフトウェア/ オープンソフトウェアのムーブメント自体に密接にかかわっていて、その 世界について、広くさまざまな人に知ってもらいたいという動機が私には あるのだ。

バックアップ

バージョンを管理するのに一番原始的な方法は、もちろんバックアッ プをとることだ。バックアップファイルの名前の後ろに通し番号をつけて 整理したフォルダに入れておけばこれは立派なバージョン管理の役割をは たすことができる。冒頭の画像の話を例にして考えてみよう。いま、 image.tiff という画像ファイルを編集しているとしよう。tiff というの は精細な画像を扱うときによく利用される形式だ。これが雑誌の表紙にな るはずのデータだとしよう。この最初の版を作ったのがたとえば 2004/03/11 の 11:30 だとする。君はまずは手始めに image.tiff を、 image-0.tiff という名前で保存する。それから背景色を変えて、少し縮 小した次の版が 13:45 分にできあがったら、これを image-1.tiff とい う名前でまた保存する。そのあと知らぬ間にボスがやってきて、さんざん ケチをつけたあと、気をとり直して次の版ができたのが 19:12。ではこれ を image-2.tiff にしよう。こんな具合だ。

図 1.1. image.tiff の縄文式バージョン管理

image.tiff の縄文式バージョン管理

ファイル名を通し番号じゃなく、時刻そのものにするのも一案だ。 たとえば、image-0.tiff のかわりに、2004-03-11-11-30.tiff のような 名前にする。これだとファイル名を見ただけで、いつバックアップをとっ たかまで一目瞭然だ。欠点としてはファイル名がすごく長くなってしまう ことで、これから説明していくにはちょっと都合がわるい。大抵のシステ ムでは、ファイルの時刻を調べる機能がちゃんとついているので、ファイ ル名自体に時刻を埋め込まなくてもそれほどは困らない。

この方法の利点と欠点について、すこし考えてみよう。まず利点。 なんといっても話が単純なことだ。それからこの手法は—これだっ て立派な手法だ—どんなデータにだって使えることだ。今は画像で 説明したけれど、同じことは見積り用の表計算のデータにだって、プレゼ ン用の提案書にだって、FAX で送る予定のお悔やみの文書にだって、校正 中のマサイ語の辞書にだって使える。1 + 1 = 2 が、りんごにも、みかん にも、象にもサイにも使えるのと同じだ。このことを示すために、 image.tiff という具体的なファイル名のかわりに R という一文字でファ イルを表して、その後にバックアップの順番を示す番号を振ろうと思う。 R はリビジョンの略だ。ファイル名を番号だけ表すのはさすがに寒いので 先頭につけてみた。あまり深く考えないでほしい。

図 1.2. 一般的なファイルの縄文式バージョン管理

一般的なファイルの縄文式バージョン管理

次は欠点。版を重ねるごとにデータサイズが大きくなることだ。い まみたいな話だとかなり複雑なデータになっているはずだから、数メガバ イトもあるかも知れない。そんなんもんじゃない? オーケー。10メガバイ トだとしよう。修正は、全体のサイズに対してわずかだろうから、版を重 ねた後もだいたい 10メガバイトだとすれば、N 回バックアップすれば N * 10 メガバイトのディスクを食うことになる。10回バックアップすれば 100メガだ。たしかにこれはあまり嬉しい状況じゃない。考えてもみてほ しい。お互いほんの少ししか違っていない良く似たデータが、いくつもい くつも自分のディスクの中で雪だるまみたいに増えていくのだ。でも、と 君は言うかも知れない。それは対した問題じゃない。最近のハードディス クの容量を見ろよ、と。数百ギガバイトの容量を持つようなものがザラじゃ ないか。3年後には、きっとテラバイト級のやつが店に並ぶぜ。100 メガ と言えばこのてのディスクの 1/1000 か、1/10000 の容量しかない。ケチ なこと言いっこなしだ。好きなだけ版を重ねても問題なんかおこりゃしな いぜ、と。

なるほど説得力がある。しかし、だ。このまるごとコピー作戦には もう一つ重大な欠点があるのだ。それは、ある版とその前後の版での修正 点が何であるかがバックアップデータを見ただけでは簡単にはわからない、 という問題だ。これはちょっと画像では説明しにくい。ワープロで作った 非常に大きなドキュメントを例にとろう。業務中にテトリスをやりすぎて クビになった君の新しいアルバイト先での第一日目。自己紹介もすまない うちに渡された巨大なワープロのドキュメントは全部で 500 ページ。行 数にして 15000行もある。何かの標準化資料という話なのだが、内容を見 てもさっぱりわからない。でも心配はない。「我々は、この文書の 内容を理解させようと君を雇ったわけではない」からだ。君の仕事 はこの文書を管理することと、レビューに出席して、丸テーブルの前で黒 いスーツとサングラスに身を固めた七人の男たちが低い声で語る修正案を 文書に反映させることだけだからだ。「ただし、正確にやりたまえ 」。君はさっそくドキュメントのバックアップをとり、最初の版、 R-0 として管理する。これでひと安心だ。次の日に最初のレビューがある。 レビューはあまり盛り上がらない。1320行目から 2 行削除してくれ、と言 われる。それから 14015 行目から 3 行追加してくれ、と。これで全部だ。 君は会議の後、修正後のドキュメントのバックアップをもう一度とる。こ れで二つ目のバージョン、R-1 ができた。次の日も、そのまた次の日もレ ビューは続く。君のリビジョンも R-2, R-3, ... と増えていく。

こんな感じでレビューが 5 回ほど続いた一週間後、ひとりの男が 重苦しい沈黙を破って「我々は、話の最初から何かとんでもない重要な条 項を削除してしまったのではないかね」と言う。一瞬、皆に緊張が走る。 最初のレビューでの変更点は何だったかね、ほら、君がやってきた、あの 日のレビューだよ、とすぐ隣の男が君の耳もとでささやく。とたんに君は 困った状況に追い込まれる。君はこの日のレビュー前のバックアップ (R-0) と、レビュー後のバックアップ(R-1)の、両方のデータを保管して いる。だから、「あの日のレビュー前の状態にすみやかに戻したまえ」と か、「あの日のレビュー後のデータを印刷して、ウクライナの国境近くに いるエージェント・ケファに直ちに送りたまえ」とかいう要求に答えるこ とはできる。しかし「ではそのレビューでの変更点は何だったのか?」と なると話は別だ。二つのファイルとは別に「1320、2行削除、14015、3 行 追加」のようなメモを管理しない以上、15000 行もある二つのファイルの 内容を一行づつ目チェックしながら追いかけていくより他ないわけだが、 もちろんこれは人間のやる仕事ではないし、君の仕事でもない。君は人間 なのだ。[1]

テキストファイルとバイナリファイル

問題を整理しよう。第一の疑問は、こうだ。「ある良く似た ふたつのデジタルデータがあるとき、その違いを常に計算することができ るか? 」、もう一つは、こうだ、「もしそうなら、その違い を人間がわかる形式で表現できるか? 」 この二つだ。ここでいう 「違い」のことを、コンピュータの世界では「差分 」と言ったり、「デルタ」と言ったりする。後者は耳 慣れない言葉だが、差分は英語で difference と言い、頭文字のd はギリ シャ文字でデルタという文字になるところから来ている。この本ではいつ でも差分と言うことにする。ここはアメリカでもギリシャでもウクライナ でもない。日本なのだ。

第一の疑問にはあっさり答えることができる。つまり、イエス、 だ。どんな場合にでも、どんな形式のデジタルデータでも、差分を計算 することができる。ドキュメントデータもデジタルデータの一種だから、 もちろん差分を計算することができる。問題は第二の疑問だ。これは非常 に難しい。R-0とR-1の差分をせっかく求めても、人間がわかる形で表現でき るとは限らないのだ。いまの例で言えば、最初の日の修正前のドキュメン トと修正後のドキュメントを指定して、その両者の差分を出力するプログ ラムを書くことはできるが、その差分が、「1320、2行削除、14015、3行 追加」とか、そこまで親切な形ではなくても、とにかく人間が解読できる ようなデータにできるとは限らないのだ。その差分データにせいぜいでき ることといえば、変更前のドキュメントと、一緒に渡して、変更後のデー タを復元するようなプログラムの存在を必ず保証できることだけなのだ。

ずいぶんと悲観的な話をしてしまったようだが、単に私は「デジタ ルデータ一般についてはノー」と言っただけだ。すべての女性にピアスが 似合わなくても、ピアスの似合う女性はたくさんいるし、すべての政治家 が公正廉直でなくても、公正廉直な政治化だって、いるにはいる。たぶん。 そんな女性や政治家を探してみよう。いま問題になっているのは、「ドキュ メントファイル」だ。しかしドキュメントファイルにもいろいろある。ワー プロのドキュメントはたいてい、行によってフォントの大きさが違ってい たり、イタリックになっていたり、段幅が微妙に違っていたり、文字その もの以外のデザインに関係したデータがたくさん入っている。これとは逆 に、単なる文字情報だけが入っていて、それ以外の情報が一切入っていな いようなものもある。豊富な情報が入っているデータにもいろいろある。 たとえばあるソフトウェア会社の作ったデータは、その会社独自のデータ かも知れない。他の会社のワープロのデータと互換性があれば、自分のと ころのソフトウェアが売れなくなる可能性があるから、わざとそうしてい るのかも知れないし、互換性の問題に気づくことができない単に無能なソ フトウェア集団なのかも知れない。いま言った、文字だけの情報が入った ファイルのことを、テキストファイル、と言う。そしてそれ以外のファイ ルをバイナリファイルと言う。さて第二の疑問の答えは、こうだ、「もし 君のドキュメントがテキストファイルであれば、差分を計算できて、その 結果を人間が把握する形式で表示することもできる。もしそうでなければ、 つまり君のドキュメントがバイナリファイルであれば、うまくいくかどう かは、そのバイナリファイルの性質による」。

君のドキュメントが運よくテキストファイルであったとしよう。す ると、二つのドキュメントの差分を以下のように表示するためのプログラ ムがある。具体的にどうやるんだよという話は、ちょっと端折らせてほし い。狭くて深いクレバスの谷底までいちいち降りていたんじゃいつになっ ても頂上には着けない。あとで詳しく説明するが、GNUdiff、グニューディ フと呼ばれるプログラムを使うと、とにかく以下の出力を手にできる。ディ フは、さっきも出てきた difference つまり差分の意味だ:

--- R-0       2004-04-12 09:52:47.000000000 +0900
+++ R-1       2004-04-12 09:52:56.000000000 +0900
@@ -1317,6 +1317,8 @@
     てまで解釈されるものではない。
 XI. 特別工作員間の通信はすべて非対称暗号方式を利用するものとし、
     具体的な形式は以下のいずれかとする。
-イ.楕円暗号
-   楕円暗号は他方法によることができない場合にのみ使用することを許可する。
 ロ.量子暗号のうち、二粒子相関系を用いたもの。
 ハ.オメガ・チャンネル(推奨)
    オメガ・ディテクターを携帯している特別工作員は常にオメガ・チャ
@@ -14012,9 +14014,6 @@
   し、又はこの条約で捕虜に与える権利を制限する恐れがある場合に限り
   行うことを認められる。但し、当該紛争当事国が外交上及び領事業務上の
   慣習及び条約に従って通常行う任務を行うことを妨げない。
+第17条の2
+  第1条から第16条までの規定にかかわらず、関係諸機関にはジュネーブ第一条
+  約、第二条約、第三条約、第四条約の各条項が厳格に適用されるものとする。

 第18条
   第3条、第12条、第14条及び第15条に掲げる特別工作員は、次の標示に関し

いったい何の話かわからないだろう。実を言うと私にもさっぱりだ がここで注意したいのは、データの内容ではなく、このファイルの構造だ。 大雑把に言って、先頭の二行を除けば、@@ -1317,6 +1317,8 @@ のような行で始まる大きく二つの部分に区 切られていることがわかると思う。これをハンクと言い、@@ の行をハン クヘッダー、と言う。ハンクとは英語で「ちょっとした大きさのかたまり」 程度の意味らしい。最初のハンクヘッダーは次のように読む「修正前のファ イルの 1317 行目から始まる 6行は、修正後の 1317 から始まる 8 行に 対応しています。対応の仕方は以下です」。次のものは、「修正前のファ イルの 14012 行目から始まる 9 行は、修正後の 14014 行目から始まる 6 行に対応しています。対応の仕方は以下です」。最初のハンクには '-' 文字で始まっている行が 2 行ある。これは行が削除されたことを示して いる。一方二番目のハンクには '+'文字で始まっている行が 3 行ある。 これは行が追加されたことを示している。先頭に記号のない行は変更があっ たまわりの様子を示すための手がかりとして置かれた行で、修正の前後で 変化がなかった行を示している。それぞれの変更がどんな内容だったのか は一目瞭然だろう。君は救われたのだ。

少し話をはぐらかしてしまったような気がして恐縮している。デジ タルデータ一般についての差分の話をしておきながら、テキストファイル とバイナリファイルに分類して、いつのまにかテキストファイルに限定し た差分の話をしてしまった。実はバイナリファイルにはテキストファイル の差分のようなうまい一般論はない。バイナリファイルに属するもっと個 別の具体的なファイル形式について議論するより他なくて、それはこの本 の内容を超えているのだ。ではこんな限定した議論に意味がないかという とそうでもない。テキスト形式のデータもたくさんあるからだ。まずまっ さきにあげなくてはならないのが、プログラムのソースコードだ。これは 何十年もの間、ずっとテキストファイルだった。そうでないコンピュータ 言語や開発処理系もあるのかも知れないがとても主流だとはいえない。そ れからドキュメント文書の一部、たとえば TeX と呼ばれるドキュメント 形式は、やはりテキストファイルだ。それから電子メールなんかもテキス トファイルだし、HTML のホームページもそうだ。他にもいろいろある。 一部の表計算のソフトなんかでも、ファイルの保存形式を選択することで テキスト形式で保存できるものもある。自分のお気に入りのプログラムが あれば、マニュアルなんかで調べてみると思わぬ発見があるかも知れない。

君の回りで、便利なソフトを使わず、わざわざテキストファイルを 使っている人がいたら要注意だ。彼は本当の便利さを理解しているのかも 知れないのだ。

差分と複数のファイル

ここまでのところをまとめさせてほしい。まず、デジタルデータに は時間の経過と共に変化するタイプのものがあって、それを管理したい場 合にはバックアップを随時とって名前をつければ良いのだが、それだとバー ジョン間の差分をすぐに知ることができない。でも一部のデジタルデータ は良い性質を持っていて、いつでも二つのバージョン間の差分を人間が理 解できる形に計算することができる。こういうファイルのことをテキスト ファイルと呼ぶ。そういうことだった。ここから先は、議論の対象になる ファイルはいつでもテキストファイルであるとする。それから、バージョ ンのことをリビジョンといいXXX、それぞれのリビジョンを、R-0, R-1, R-2 ととおし番号で呼ぶことにする。混乱してきたら、R-0 とかは日付と時間 の入ったファイル名のことだと思い出してほしい。たとえば ... という 具合だ。

さて、前の節で示した、二つのリビジョンの間の差分をとるプログ ラムの話だが、別にこれは私が作ったプログラムじゃない。何十年も前に ハッカーたちが協力して知恵を出し合ってつくったもので、GNUdiff とい う名前のプログラムだ。「グニューディフ」と読む。何でこんな奇妙な名 前なのかは話すと長い。単に「ディフ」と言っても通じる。それから、こ のディフとペアになったもう一つの有名なプログラムがある。それは GNUpatchと言う。「グニューパッチ」と読む。こちらも「パッチ」と言え ばその手の人たちには通じる。ディフの方はもう説明した。パッチはこれ とちょうど逆のことをするプログラムだ。つまり、あるリビジョンと、差 分を与えて、変更後のリビジョンを復元するプログラムだ。つまり:

図 1.3. 一列に並んだリビジョン

一列に並んだリビジョン

のようになっているとき、R-0 と R-1 を GNUdiff に渡すと、R-0 とR-1の差分を計算してくれる。これを diff(R-1,R-0)と書くことにする。 R-1 のほうを先に書くのは、差分をとる処理がちょうど引き算に似ている から、R-1 引く R-0 という目で見たいからだ。GNUpatch は GNUdiffの ちょうど逆のことをする。つまり diff(R-1,R-0)とR-0 を渡すと、R-1 を 復元してくれるのだ。

図 1.4. GNUdiff の処理イメージ

GNUdiff の処理イメージ

図 1.5. GNUpatch の処理イメージ

GNUpatch の処理イメージ

diff(R-1,R-0)なんて書いても、ピンとこないかも知れないが、前の 節のドキュメントの差分を思い出してほしい。あの形のものを指している だけだ。いちいちあの表示を書いていたら紙が持たない(本当は紙じゃな いけど)し話がまわりくどくなってしまうので、ご勘弁願いたい。R-0 とか R-1も、例の 15000行のドキュメントにちょこちょこ修正が入ったようなものを イメージしてほしい。ああいうものを指している記号だ。話は脱線するが、 シンボルの力は偉大だと思う。「車」と書けば、実際の車を用意しなくて も車について語ることができるし、「宇宙」と書けば、実際に宇宙を用意 しなくてもとりあえずは宇宙について語ることができる。時には話をは しょった見返りに、実物にでくわした時に、手痛いしっぺ返しを受けるこ ともあるわけだがそれはまた別の話だ。

さてここまで道具立てがそろうと、この章の最初のバージョン管理 の手法、つまり単なるバックアップファイルの蓄積より、もう少しスマー トな管理手法をとることができる。バックアップファイルほどディスクを 消費しないし、同時にリビジョン間の差分を即座に見てとれるという一石 二鳥の方法だ。それをこれからお見せしよう。

まず、元のバックアップ手法のリビジョンを一列に並んだところを もう一度思い浮かべてほしい。各リビジョンでの修正量が少なければ、こ れらのデータはよく似ているのだった。これらのリビジョンの隣り合う二 つに対して、GNUdiff を呼び出して、差分を求める:

図 1.6. 隣り合うリビジョン間への GNUdiffの実行

隣り合うリビジョン間への GNUdiffの実行

そして、命知らずにも、R-1 から R-3 までのファイルを削除する。 すると以下のようなファイルが残る

図 1.7. 最初のリビジョンと差分の集まりだけを残したところ

最初のリビジョンと差分の集まりだけを残したところ

d(rN,rN+1)の形のファイルは普通はとても小さい。前の例の行数を 実際に数えてみてほしい。30行にも満たない。これに対して、R-0, ... R-3 のようなファイルは非常に大きい。修正の量にもよるが、どれも大体 15000行 くらいだろう。だから、バックアップ方式だと 15000 × 6 = 90000行のデータを保管しなくてはならない。一方、差分は普通はどれも 小さい。余裕を見て平均 60 行としておこう。それでも R-0 と差分の全体 では、15000 + 5 * 60 = 15300 行にしかならない。ほとんど R-0 そのも ののサイズではないか。差分の内容はすぐにわかるし、データサイズも小 さくて済む。あとは各リビジョンをうまく復元できるかどうかなのだが、 GNUpatchを使えば求めることができる。まず R-0 はすでに手にしている。 R-1 は、R-0 と diff(R-1,R-0)をGNUpatchに渡せば求めることができる。R-2 はいま求めた R-1 とdiff(R-2,R-1)を再び GNUpatchに渡せばいい。こんな風 に繰り返しGNUpatchを呼び出せば、リビジョンの数がどんなに増えてもい つかは欲しいリビジョンが求まる。図で書くとこうだ。

図 1.8. GNUpatchによる各リビジョンの復元

GNUpatchによる各リビジョンの復元

でも、R-0 と diff(R-1,R-0)... などから次の R-4 を作るにはど うしたらいいんだろうか? それにはこうする。まず今いった方法で何回も 繰り返し GNUpatch を呼び出して R-3 を作る。そしてこれを R-4 という 名前にコピーする。このままではまだ R-4 は R-3 と一緒だ。それから、 例の冷や汗もののレビューで君はこの R-4 に修正を加えて保存する。こ れで晴れて R-4 ができた。それからさっきよけておいた R-3 と R-4 の 差分 diff(R-4,R-3) を GNUdiff を使って計算する。これを差分のリスト に追加して R-3 と R-4 を削除する。これでおしまい。

今回の差分作戦の基本は以上だが、この発想の上でいろいろな改良 を加えることはできる。たとえば、差分ファイルでディレクトリやフォル ダが一杯になってしまうのを防ぐために、R-0 と残りの差分全体を一つの ファイルにまとめてしまえるような、新しいファイルの形式を定義してや る。そしてGNUpatchとGNUdiffをうまく改造して、この新しいファイルか らデータを取り出したり、好きなリビジョンを取り出せるようにしてやる。 複数のファイルをアーカイブというソフトを使って一つにまとめた経験は ないだろうか、ちょうどあんな感じだ。

図 1.9. 差分の集まりをひとつのファイルにまとめた様子

差分の集まりをひとつのファイルにまとめた様子

これでいくら差分ファイルが増えていっても、その新しいファイル の内容がどんどん増えるだけで、ディレクトリがファイルで一杯になった りすることはなくなる。それから、差分の内容をすぐに思い出せるように、 差分のそれぞれに小さなメモつけることができるようにしておく。バージョ ン管理システムの世界では、このようなメッセージをログメッセージとか、 単にログとか呼ぶ。ちょうど好きなカセットテープのケースに「いとしの あゆ」とか書くのと一緒だ。こうしておけば、この一つのファイルの中に、 このファイルが最初のリビジョンから現在にいたるまで辿ってきた、すべ ての歴史が刻まれていることになる。そしてインディージョーンズが謎の 古代文字を解読するように、君はすべての過去にアクセスし、そこに流れ る人の思いを辿ることができるのだ。このような仕組みを作るための具体 的なプログラムをイメージできないとしても、おおよその雰囲気はわかっ てもらえるのではないかと思う。

さらにいろいろな改良を加えることができる。いままでの例ではたっ た一つのファイルをバージョン管理してきたが、一般には複数個のお互い に関連のあるファイルを一緒に管理することが多いだろう。たとえば 15000行の一つのドキュメントはいかにも大きすぎる。このドキュメント が 3 章からできているのなら、三つのファイルに分けて管理したほうが 楽だろう。ディレクトリ中にはファイルごとの差分がどんどんできていく が、いま述べたようにもとのファイルとそのファイルの差分を一つのファ イルにまとめる手法を使えば、いつまでたってもディレクトリのファイル の数は 3 個のままだ。こうしてバージョン管理の対象は単一のファイル からあるディレクトリ全体という、より豊富なデータ構造に移ることにな る。そして単一ファイルのバージョン管理は、たまたまバージョン管理す るディレクトリに一つのファイルだけが存在するという特殊なケースとみ なすことができる。

細かい、と君は言うかも知れない。あんたの言うことは細かい。要 するに、こう言いたいんだろう。バックアップファイルをたくさんとるか わりに、もっと効率が良くて、変更点もすぐにわかる一石二鳥の方法があ ると。それを使うにはなんとかって言う二つのプログラムを使えばいい、 と。やり方はこれこれ、こうだ、と。あとはこのやり方にしたがって、そ のグニューなんとか をうまく組み合わせたプログラムを作ってくれ、と。 しかし、だ、これじゃ、エンジンのパーツ一式とドライバとスパナを俺に 渡して、はい、さようならって言ってるようなもんだ。いいか、言っとく けど俺はプログラムのことなんてぜんぜん知らない。あんたには簡単かも 知れないけど、俺はそんなもん組み立てたことなんてない。できるやつに 頼めって? なるほど、会社にはすごい詳しいやつが二人いる。特にその一 方はすごいらしい。俺には二人とも同じように、なんだかすごい連中だと しか見えないが、その滅多に口を利かない片方が、もう一方のことを天才 と言うんだ。だからおそらく相当すごいやつなんだろう。しかし、だ。俺 はこいつが気に入らない。ピカイチ気に入らない。人を見下してばかりい る嫌な野郎だ。俺にはわかる。ああいう奴にはプログラムが組めない人間 はみんなバカに見えるんだ。なにさまのつもりだ。はっきりいってこんな 男にモノを頼むくらいなら、舌を噛み切って死んだほうがよっぽどましだ。

なるほど、かなり深刻そうだ。しかし、実際には油まみれになって エンジンを組み立てる必要もないし、少なくともこの件では君も命を落と さずに済む方法がある。ちょっとわざとらしいのだが、実はいま君がまさ に言ったようなものを、すでに組み立ててくれた人がいるのだ。人という のは正確じゃないかも知れない。人々、それも大勢の人々、しかも長い時 間をかけて、しかも大した見返りもなしに、だ。このいきさつと経緯につ いての物語は、それ自体とても面白いのだが、別の機会に譲ろうと思う。 とにかくここから先、もう君は GNUdiff と GNUpatch のことを、近所の ゲーセンにおいてある 2ゲーム100円のリセットボタンみたいにきれいさっ ぱり忘れることができる。テレビの中のごちゃごちゃした部品についての 知識がなくてもリモコンをいじれば、なんだか知らんがテレビは見れるし、 百円玉を自動販売機に突っ込めば、なんだか知らんがコーラが出てくる。 同じことだ。スイッチポンで脱水、乾燥、柔軟仕上げ。かしこい主婦なら 迷わずえらぶ全自動洗濯機みたいなソフトがある。それが CVS、コンカレ ントバージョンシステム、だ。次の節ではこのソフトについて少し話をし ようと思う。ところで君んとこのイヤな野郎の話だが、そいつが嫌なやつ だからって、コンピュータに詳しいやつがみんなそういう連中だなんて思 わないでほしい。君の専門が何か私は知らないが、どんな分野だって、本 物っていうのは決して多くはないものだ。私は言ったはずだ。公正廉潔な 女性もたくさんいるし、ピアスの似合う大物政治家だって、いるにはいる のだ。たぶん。

協力者たち

ものすごい駆け足で説明してきたが、こういうアイディアは昨日の 今日で一人の人間の頭の中だけで思いつくものではない。私の知る限り、 おそらく 20〜30年くらいの歴史の中で少しずつ少しずつさまざまな議論 を通じて育ってきたものだ。そして今から数年前に、一応の完成をみた。 このシステムをコンカレントバージョンシステム、CVS と言う。CVS は今 言ったような形式で、複数のファイルをひとつにまとめたディレクトリ、 あるいはツリーを管理することができる。CVS の細部は、とてもここで語 り尽くせるものではないが、今までの議論で触れていないひとつの大きな 特徴がある。それは、分岐、という概念だ。GNU arch が作られた最も大 きな理由の一つは、CVS の持つ、この分岐概念の不完全さからくるので、 以下の節では分岐、そしてこれをペアになる「マージ」ということについ て詳しく説明しようと思う。分岐とマージは、今までの例のように一人で データを管理しているときには表に現れない。しかし複数の人間が協調し て一つのデータを管理する場合には本質的なものとして現れるのだ。

さて、ここで CVS について最低限の説明をしようと思う。前の節 で言ったように、生の GNUdiff と GNUpatch を使いやすくまとめて誰で も使えるようにしたパッケージを作ろうという動きは非常に早くからあっ たようだ。CVS はこの流れの中で数年前に一応の完成を見た。実はこのド キュメントを書くに当たって、CVS が完成に至る過程を詳しく追いたかっ たのだが、ネット上を検索してもなかなか良い文献には出会えなかった。 唯一参照できそうだったのが CVS に関連したメーリングリストの情報で、 いくつかのリストについては 1993/2 くらいまで遡れるものもあるような のだがアーカイブ全体をテキストファイルに落すことができず、結局詳し く追体験するには至っていない。私はこれらの歴史に非常に興味があるの で、バージョン管理システムの過去について詳しい方や、CVS 関連の非常 に古いメーリングリストのアーカイブなどを保存されておられる方がいた ら是非私に御連絡頂きたいと思う。いずれにせよ、CVS は昨日の今日でで きたようなシロモノでないことだけは確かだ。私の知る限り、20〜30年く らいの歴史の中で、多くの人々の議論の中で徐々に形をとっていたものだ と考えられる。この物語の中には「一人の天才」のようなドラマはないこ とだけは確かだ。人間一人では何にもできない。

ここでは CVS の膨大な機能の中で、基本となる部分と、GNU arch との関連で重要な「分岐」という応用機能についてしぼって説明しようと 思う。

CVS では二人の登場人物がいる。一つは、「リポジトリ」と呼ばれ るデータ格納庫。もう一つはこの「リポジトリ」にデータを追加するのに 必要な補助的な領域である「作業コピー」だ。「リポジトリ」というとな んだか高尚なもののようだが、実はもう我々はどんなものかイメージする ことができる。そう、前の節で図に書いたような、最初のリビジョンと追 加の差分情報が蓄積されたファイルを集めたディレクトリのことだ。この ディレクトリには、ディレクトリ内にあるすべてのファイルの、全ての履 歴情報が入っている。リポジトリからは、任意のリビジョンのデータを取 り出すことができるし、最新のリビジョンに次の差分を追加して、新しい リビジョンを作ることもできる。リポジトリはとても重要な場所なので、 直接編集したりすることは許していない。かならす CVS システムに対し てこれこれのことをしてくれ、と頼まなくてはならない。これはちょっと 窮屈に思えるかも知れないが、CVS にできる操作しか許さないことで、リ ポジトリのファイルを間違って削除してしまったり、勝手に名前を変えて しまったりといった操作ミスをなくすことができる。閉架式の図書館みた いなものを想像してもらってもいい。本を読みたいと思ったら直接本棚に 行くのではなく、係の人にとってきてもらう。あれと一緒だ。もちろん CVS はなにか神秘的なことをやるわけじゃない。内部的に前の節で話した GNUdiff や GNUpatch を使って一所懸命必要なリビジョンを計算して、君 のためにとってきてくれるというわけだ。あまり詳しくない人から見ると、 リポジトリはものすごい数のリビジョンデータ全体がある巨大な格納庫に 見える。しかし実際には最初のリビジョン以外は差分の集合体なのだった。

もう一つの重要な登場人物が作業コピーと呼ばれる場所だ。CVS か らデータを取り出そうとすると、作業コピーが作られてそこにデータがコ ピーされる。ただコピーされるわけじゃなくて、どのリポジトリから取り 出したか、とか、取り出したリビジョンはどれか、などの情報も記憶して いる。作業コピーは同時に何人でも作ることができる。CVS が呼び出され るたび、呼び出した人用の作業コピーができる。これは閉架式の図書館と は違うところだ。現実の本と違って、デジタルデータはいつでもコピーす ることができるのだ。このコピーを作るための命令を checkout と呼ぶ。 CVS の基本コマンド、その1だ。

図 1.10. CVSに依頼して作ったふたつの作業コピー

CVSに依頼して作ったふたつの作業コピー

CVS での基本的なワークフローはいたって単純だ。まず、リポジト リから最新のリビジョンを作業コピーに checkout 命令で取得する。それ から作業コピーに対して必要な修正を加える。これでいいなということに なったら、CVS システムに対して、今回の作業コピーの内容をリポジトリ に追加してくださいという命令を送る。すると CVS は現在の最新リビジョ ンと作業コピーとの間の差分をとる。それからできた差分をリポジトリを 構成する各ファイルに追加する。この操作を commit と言う。基本コマン ドその2だ。なんだか CVS はエラク高尚なことをしているように思うかも 知れないが、実際には前節で紹介した GNUpatch とか GNUdiff のような プログラムがやるのと同じようなことをしているだけだ。get して、コミッ トする。この繰り返しによって、リポジトリのリビジョンはどんどん増え ていく。

他にも CVS はいろいろなことができる。たとえば、最新リビジョ ンよりも前のリビジョンを取り出すこともできるし、あるリビジョンと別 のリビジョンの差分を計算して、表示させることもできる。既に少し説明 した、ログメッセージの内容を表示させることもできる。これを見れば、 ああ、あの時のコミットは、こんなことをやったのだった、と見当がつく。

話がこれで終ってしまうのなら、CVS は GNUpatch と GNUdiff の やったことを一手に引き受けてくれているだけで、あまりありがたみがな い。CVS が便利なところは、複数の人間がそれぞれ作業コピーを作って同 じリポジトリにコミットできるような仕組みを提供しているところだ。 CVS の C はコンカレントの C だが、それはこのことを意味している。 ちょっと考えればわかるように複数の人間が勝手に checkout して修正を コミットすれば、修正がお互いに衝突してしまったり、相手のした修正点 に気づかず上書きしてしまったりするのは想像がつくだろう。詳しい説明 は省略するが、CVS はこの当たりの交通整理もしてくれる。ある人が修正 した部分に別の人が更に修正しようとすると警告してくれたり、まずは他 の人がした修正点がどんなものであったかを自分の作業コピーに受け取る ように指示してくれたりする。

分岐、そしてマージ

CVS について説明した。CVS は GNUpatch と GNUdiff をうまく組 み合わせて統合したソフトで、基本的な命令 get と commit を持ってい るのだった。get を使って作業コピーと呼ばれる場所に、バージョン管理 されたデータを読み込んでは修正し、一段落したら commit して、元のデー タに差分を追加していくのだった。実際にやっていることは要するに GNUpatch や GNUdiff と変わらないのだが、使い勝手はずっと良くなって いるし、GNUpatch や GNUdiff や差分の仕組みのことを知らない人でも気 軽にバージョン管理の恩恵にあずかれると、こういう話だった。利用者が 知っていなくてはならないのは、差分とか、特殊なファイル形式とか、繁 雑な GNUdiff/GNUpatch の操作ではなく、リポジトリ、作業コピー、 get/commit のような、もっと次元の高い概念だけでいいのだった。さら に CVS は複数の人間が get / commit する場合でも、お互いの変更がか ぶったりしないように調整したり、同時に複数の人が commit しないよう に、うまく交通整理してくれると、こういうわけだった。合言葉は「スイッ チ・ポン」だ。これが世界を救うのだ。

ここでは最後の、複数の人間の共同作業、というところをもう少し 堀下げて考えてみたい。ある一つのデータをみんなで協力して改良したり 修正している場合には get/commit だけで十分だ。たとえばいまずっと問 題にしてきた、国家間で利用されるある重要なドキュメントに対して、帰 りがけに A が 10243行目の誤字に気がついたとする。A は時計とにらめっ こしながらCVS に頼んで作業コピーに最新リビジョンの内容を get する。 作業コピーの上で10243 行目を修正する。そして CVS に頼んで commit する。ばっちりだ。でももしかすると B もちょうどそのとき同じ間違い に気づいてやっぱり自分の作業コピー上で10243 行目を修正してコミット してしまっていたとする。そんな時は CVS は、その修正はもう B がやっ てるよと教えてくれる。そして commit は失敗するが、もちろんその失敗 は意図したものだし、手柄が A じゃなく B のものになっただけで誰も困 らない。

しかし、もう少し複雑な状況を考えてみる。いまは、たった一つの ドキュメントをめぐっての作業フローだった。でも、以下のようなことも、 よくおこる。基本的にはこのドキュメントと同一の内容を持っているのだ が、内容の一部がほんの少し違っているようなものが欲しくて、しかもそ れはそれで独立した文書としてずっと管理していきたい、という場合だ。 たとえば、この国家間ドキュメントには、なんらかの非常に重要な機密事 項も含まれていて、各国の首脳級レベルの人間以外には配布したくない、 と。でもそのような部分は非常にわずかで、それ以外の部分については各 地に散らばっているエージェントに配布したい、と。極秘版と、一般大衆 版のふたつのバージョンが欲しい、と。

そんな重要な文章の機密内容を、俺や Hally や Sally 程度の人間 が編集できるもんかと言うかも知れない。ではもう少し現実的な例を出そ う。そのためには君にプログラマーの役を演じてもらう必要があるが、も 実際にそんな知識が必要なわけではない。学芸会に出てくる南の国の王様 みたいにそのまま椅子にふんぞり返っていてくれればいい。いま、ある企 業が新しいソフトウェアを開発している。このソフトウェアは有料なのだ が、よくあるように、評価限定版というのがあって無料でダウンロードし て利用できる。評価限定版は、製品版と、うり二つだ。ただし、30日たつ とすべての機能が利用できなくなってしまう。そこだけが製品版との違い だ。評価版 = 製品版 + 30日タイマー、と書き表すことができる。

図 1.11. 評価版 = 製品版 + タイマー

評価版 = 製品版 + タイマー

ところで、ソフトウェアには間違いがつきものだ。これをバグと言 う。ソフトウェアが完成したらバグも全部なくなっていると思うかも知れ ないが、そんなことはない。出荷したあともいろいろなバグが見つかるし、 そのバグは修正していかなくてはならない。もちろん大きなバグ、利用す るのに致命的なバグというのはなくなっている。でなければそんなソフト 買う人なんていないだろう。この細かいバグには作り手もユーザもいつも 悩まされる。作り手は新しく何かを作るではなく、既に作ったものを保守 しているわけだから、やる気も失せてしまっている。それにバグを直した つもりが、別のバグを生んでしまうことがある。笑うかも知れないが、こ れは本当によくおこることなのだ。逆に、ユーザはしみ一つない動作をす ると期待してソフトを買ったのに実際には細かい動作が意図したように動 かない。評価版が用意されているのにはこんな理由がある。もし評価版を 使って問題があれば、買わなければいい。あるいはここを直してくれたら 買うんだが、とその会社に E-mail してあげてもいい。

ながながと書いてしまったが、評価版 = 製品版 + 30日タイマー、 となっていた。評価版に新しいバグが発見されたとする。すると、それは 製品版と共通の部分に含まれているか、30日タイマーの部分に含まれてい るかのどっちかだ。共通部分に含まれているなら、評価版のバグを修正し たら、製品版にも反映させなくてはならない。たとえばプログラム開始時 に「ようこそ、このソフトウェアへ」という文言が間違って「そうこよ、 このソフトウェアへ」と表示されてしまったら、これは共通部分に含まれ ているバグだ。でも 30日タイマーの部分なら、製品版の方には反映させ てはいけない。たとえば 30日ではなくて、60日たって使えなくなったら、 これはタイマーのバグだ。評価版と製品版は、とてもよく似ている。そし てほんの少し、つまりタイマーの部分だけ、ちょっとだけ違っている。そ してそのちょっとだけ違っている部分を保ちながら、両者を厳密にそれぞ れ管理していかなくてはならない。もし 30日タイマーの部分を不用意に 扱って、そこに別のバグが生まれてしまったら、タイマーは働かず、評価 版はいつまでも使えるようになってしまうかも知れない。これでは会社が もたない。

CVS では、こういう状況がうまく扱える。これを分岐、と言う。そ して分岐を作ることをブランチ化すると言う。英語では動詞も名詞も branch という一つの言葉で表せるので都合が良いが、日本語の場合だと 場合におうじて分岐と言ったりブランチと言ったりする。今の例では、お そらく製品版の方が先にあったはずで、そのためのリビジョンが CVS リ ポジトリに並んでたはずだ:

図 1.12. リポジトリ内に一列に並んだリビジョン

リポジトリ内に一列に並んだリビジョン

話が違うんじゃないかと思う人もいるかも知れない。CVS のリポジ トリは初期リビジョン+差分の集まりだと説明したばかりじゃなかったの か、と。絵が縄文式に戻っているぜ、と。その通りなのだが、ここから先 は実際のリポジトリの内部構造は忘れてしまうことにする。そういうコマ ゴマした詳細を隠すためにできたのが CVS だし、ここからの議論には内 部構成は関係しないからだ。利用者から見れば、リポジトリにあるものは 時間と共に増えていく一方のリビジョンの集まりだ。上の図ではそれぞれ のリビジョンを数字だけで表している。これで十分なのだ。

ここから、評価版のための分岐を作る。このためのコマンドは紹介 しないが、やはりスイッチ・ポンで分岐できる。分岐した後は、CVS リポ ジトリの中はこうなる:

図 1.13. 分岐後のリポジトリの様子

分岐後のリポジトリの様子

二つの横に伸びた線のことを、開発ライン、と言う。そして、最初 からあった製品版の開発ラインのことを幹といい、後から分岐してできた 評価版の方の開発ラインを枝、と言う。もちろんこれは開発ラインが分岐 している様子を一本の木にたとえたものだ。幹は英語で trunk, 枝は branch で、みき、とか、えだという言葉がおさまり悪い時には、状況に 応じて、トランク、ブランチ、とそのまま書いたりすることもある。こん な風に CVS リポジトリの中にはふたつ以上の開発ラインを分岐させるこ とができる。いままでずっと説明してきた一本の開発ラインはその特別な ケースになっていることがわかると思う。注意して欲しいのは、トランク 内にある数字で示されたリビジョンとブランチ内の同じ数字で示されたリ ビジョンは何の関係もないということだ。数字はそれぞれの開発ライン中 でのリビジョンの番号を示しているだけで両者は独立した別のデータだ。 図中トランクのリビジョン2 からブランチのリビジョン 0 に矢印が伸び ているが、ここで分岐がおきたことを示している。だからこの二つのリビ ジョンの内容は全く同じものだ[2]

枝と枝との間では、両者に共通の修正点をお互いに取り込むことが できる。これをマージと言う。もちろんすでに説明したように、タイマー のバグの修正を製品版にとりこんじゃいけない。とりこむのはメッセージ の間違いの修正だけだ。たとえばこんな感じ:

図 1.14. 修正点の選択的なとりこみ

修正点の選択的なとりこみ

詳しく説明すると、トランク側の、2->3, 3->4, 5->6, 6->7 で追 加した修正はブランチ側に取り込まれていない。だから具体的にどういう バグかはわからないが、とにかく製品版にだけ関係したプログラムの間違 いだったのだろう。逆にブランチ側の 0->1, 2->3 はトランク側には反映 されていないので、評価版のみのバグ、おそらくタイマーに関係したバグ の修正だったのだろう。またブランチ側の 3->4 の差分はトランク側7 で 取り込まれている。だからこれは両方の開発ラインで共通のメッセージの 間違いのようなものだったのだろう。トランク側 4->5 についても同様だ が、最初に発見したのはトランク側開発チームで、それをブランチ側がと りこんでいる。こうして トランク と ブランチ の開発ラインは、共通の 修正点については同期して、片方にしか関係しない修正点についてはきち んとその違いを保存したまま、時間にそってしずしずと行進を、いや、更 新をつづけていくのだ。

さあ、CVS について大分説明してきた。細かい話は別にして、以上 が CVS の持っている機能の大部分だと考えてもらってよい。君は言うか も知れない。ブラボー。すばらしい。で、君はいったい何が不満なのだ、 と。

私の答えはこうだ:CVS の分岐概念には、根本的な欠陥がある。

ブルーな日々

私の目の前に一台のパソコンがある。Linuxというフリーソフトウェ アが動いている。自分で設定したものだ。このコンピュータはインターネッ トに接続されていて、その気になれば、誰でもアクセスすることができる ようになっている。「その気になれば」と言ったが、これには二つ意味が ある。まず、私がその気になることで、もう一つは実際にアクセスしよう とする相手もその気になることだ。単にアクセス、と言っても、実はいろ いろな方法がある。いくつかの方法については、私は誰でもアクセスして 良いように設定してある。たとえばいくつかの Web ページは誰でも見る ことができる。それを使って私は情報を外部に発信しているから、見るこ とのできない人がいると都合が悪いからだ。だから、この件では私はすで にその気になっている。あとは相手がその気になるだけだ。つまり私のペー ジに興味を持ってくれて、URL をブラウザに打ち込めばいい。これは一番 よく知られたアクセス方法だが、実は他にもいろいろある。たとえば telnet と呼ばれている方法があって、このアクセスを許すと、私のコン ピュータに対して、非常にたくさんのことができるようになる。コンピュー タには私にとって大切なものも含まれているので、私は telnet でアクセ スできないように設定してある。つまり私はこの件では「その気に」なっ ていない。だから外部の人間がいくら「その気」になっても私のマシンに telnet することはできない。まずは私が「その気」にならなければなら ないのだ。

図 1.15. コンピュータといろいろなサービス

コンピュータといろいろなサービス

今は、私と、それ以外の人との間で線引きしたが、実はもっと細か くアクセス制御することができる。たとえば、Hally と Sally にだけ telnetを許して、それ以外の人、たとえば例の天才君には許さないように もできる。会員制のホームページを見たことはないだろうか? ある画面ま で行くと、ログインiDとパスワードを入力してくれ、という画面に飛ばさ れるだろう。そう、私はあのことを言っている。あれは Web サービスに 対するアクセス制御の一種だ。そのサービスが動いているコンピュータの 管理者が、決まった人しかアクセスできないような設定をそのコンピュー タにしたから、君はおいそれとはアクセスできない。そうか。最初からこっ ちの例で説明すればよかった。

図 1.16. コンピュータとアクセス制限

コンピュータとアクセス制限

CVS も、Web アクセスや、telnet と同じようにできる。つまりCVS をうまく設定して、CVS のリポジトリのあるサーバをインターネットにつ なげてやると、どこからでも CVS を使えるようにすることができる。つ まり、いままで説明してきたスイッチポンを、出先のコンピュータからも できるようになる。この場合、get コマンドで作成される作業コピーは出 先のコンピュータにできる。修正点を commit すると、今度はインターネッ トの上をデータが逆向きに流れて、作業コピーからリポジトリに向かって データが流れて、結果がリポジトリに追加される。だから君は世界中のど こにいても作業ができる。たとえば Sally がタンザニアに出張になった とする。Sally は例のソフトウェアのプログラムを管理している CVS リ ポジトリの入ったマシンに、タンザニアのインターネットカフェからアク セスできる。もちろん CVS リポジトリには適切なアクセス制御が必要だ。 これは会社の重要な資産が入ったサーバだから、外部の人間に勝手に get やcommit されては困る。だから君とHallyとSallyだけがアクセスできる ように設定されているのが普通だろう。

図 1.17. CVS サービス専用機とアクセス制限

CVS サービス専用機とアクセス制限

「設定されている」などと不用意に書いてしまったが、別にコン ピュータ自身が場の空気を読んで、君や Hally や Sally を自動的にそっ と設定してくれるわけではない。コンピュータはそんなことはしてくれな い。実際には誰か生身の人間が「設定する」のだ。じゃあ誰がやるのだろ う。君の今までの話を総合すると、君もHallyもSallyにも、ちょっと荷が 重そうだ。こういう時には会社の中にシステム管理者と呼ばれる人がいて、 その人に設定を頼むことになる。「こんど、これこれの仕事にかかわるこ とになったから、例のリポジトリに get/commit をする必要があるんだ。 悪いけど設定してもらえないかなあ」君は100万ドルのスマイルで誰かに に頼む。もしかすると頼む相手は、君がこないだ言ってた天才君なのかも 知れない。もしそうなら君の笑顔に私は同情する。いずれにしても君は誰 かに頼む。機嫌がよければ、あるいは Sally が一緒ならコンマ2秒で設定 してくれるだろう。でもあいにくその日は朝から雨で、彼は奥さんと新発 売のポテトチップスの空袋が不燃ゴミか否かをめぐって大喧嘩をしてきた ばかりで、通勤電車の中ではハイヒールを履いた若い女性に踏まれ、駅の 売店では 150円少なくお釣りを渡され、工事中のマンホールにあやうく落 ちそうになり、よけたはずみで、ガムを踏んでしまい、あげくのはてに会 社に来てみると、メールボックスが新型ウィルスのまきちらしたスパムで 一杯になっていたとしたらどうだろう。私ならこう考える。「今日はやめ ておこう」。そしてそのまま Sally のデスクに言って、明日は丈の短い スカートで来てはくれまいかと頼む。

私が言いたいことはこうだ。システム管理者の許可なしには誰も CVS リポジトリにアクセスすることはできない。国立博物館の特設会場に 展示してあるガラス張りのミイラと一緒で、君はリポジトリに指一本触れ ることができない。作業できるもできないもシステム管理者の腹一つなの だ。一つの企業内の話なのだからこれでもいいのかも知れない。いや、む しろ好ましい場合さえある。しかし、現実のデータ管理にはもっといろい ろな形態があるのだ。たとえば、先のソフトウェアで、有償版は自社で作っ たが、ここで社内の担当者は燃え尽きてしまい、タイマーの部分について は子会社に発注するようなこともありうる。いま言ったように CVS はネッ トワーク越しに利用できるので、子会社からもget/commitができる。しか しそのためには、あなたの企業のシステム管理者は子会社の人たちにも許 可を設定しなければならない。CVS はもちろんセキュリティーのことを十 分に考えた設計になってはいる。しかし子会社にはどんなモラルの人間な のかはっきりしないし、身元があまりはっきりしない外部の人間にいろい ろなアクセスを許すのは管理上問題がおきやすい。リポジトリに書き込み を許す場合はなおさらだ。commit はリポジトリに対する書き込み処理な のだ。

図 1.18. CVS サービス専用機と子会社からのアクセス

CVS サービス専用機と子会社からのアクセス

でも、CVS には分岐の機能があった。タイマー機能の枝を分岐して、 そちらの部分にだけ子会社の人にアクセスさせれば良いではないか、と。 そういう機能は CVS にはない。それに同じマシンの上に二つの枝がある から、このコンピュータがディスク障害を起こすと、両方の枝のデータが 消えてしまう。もし分岐がネットワーク上にある別のマシンの別のリポジ トリの中に作ることができれば問題は解決する。つまり、子会社の中にも CVS リポジトリを持つサーバを用意して、インターネットにつないだあと、 元のリポジトリにある有償版の分岐を、このもう一つのマシンのリポジト リの中に作れば問題は解決する。しかし、CVS の分岐は、同一マシンの同 一リポジトリ内にしか作成することができないのだ。もうお分かりだろう。 私が CVS の分岐の根本的な欠陥というのはこの事実を指しているのだ。

図 1.19. CVS の分岐の限界

CVS の分岐の限界

こんな風に書くと、私は何かことさら特殊なケースを持ち出して CVS の欠点をあげつらっているかのように見える。しかし、これは一般的 な状況なのだ。特にフリーソフトウェアを開発するときにこういう事態に よく出くわす。ちょうどいい例がある。私は GNU arch のリポジトリを Webブラウザで閲覧するための ViewARCH というフリーソフトを作ってい る。こんな場合、読み込みアクセスを世界中に許して、そのソフトウェア を公開するのが普通だ。もちろん私もそうしている。フリーソフトウェア は誰にも自由に使ってもらうことを意図して作られるし、こうしておけば、 悪い部分を誰にでもすぐに指摘してもらえるからだ。しかし普通書き込み アクセスは許さない。私も許していない。さて地球の裏側の誰かが私のソ フトに興味を持ったとしよう。そしてどこかにバグを見つけたか、新しい 機能を追加しようと思ったとする。私が CVS でこのプログラムを管理し ていたとすれば、この地球の裏側の人間に対して、私のマシンに対するア クセス許可を与えなくてはならない。しかし、このような人間とは通常電 子メールのようなもので知り合うだけで、面識はないことが多い。実際に 会うことは一生ないような人たちも多い。こんな状況でその人間に簡単に アクセス権を与えるわけにはいかない。もちろん信頼できる良識のある人 間だとわかれば、アクセスを許すことができて、分岐の仕組み自体はもっ ているのだから、CVS を使って自分のバージョンと彼のバージョンとを一 つのリポジトリ内にうまく共存させることができる。時々の彼の枝の内容 を見て気に入ればマージすることもできる。彼も自分オリジナルの変更を 自分の枝に加えながら、私のアイディアを取り込むこともできる。しかし これらはどれも彼にアクセス権を与えて初めてできることなのだ。

もし分岐を、ネットワークの他のマシン上に作ることができて、そ の枝同士でマージができれば、問題は解決する。このような機能 をもったバージョン管理システムは、ネットワーク上にさまざまなリポジ トリが分散して存在するので、分散型のバージョン管理システム、と呼ば れる。これに対して CVS のように、ひとつのマシン上のひとつのリポジ トリだけで世界が閉じているバージョン管理システムを集中型のシステム と言う。GNU arch 分散型バージョン管理システムとして設計された。い ま述べてきたことは GNU arch では簡単にやることができる。分岐を作る ときには分岐元のマシンの管理者は、自分のマシンに特別な設定をする必 要は何もない。通信ログを見なければ、地球上の誰かが自分のリポジトリ の分岐を作ったことに気づきさえしないだろう。

図 1.20. GNU arch の分岐はリポジトリの境界を越えることができる

GNU arch の分岐はリポジトリの境界を越えることができる

GNU arch

ずいぶん長々と述べてきた。ここでまとめようと思う。

GNU arch にはこのほかにもさまざまな改良点を持っている。その どれもがすばらしいものだが、ここでは分散型の性質だについて徹底的に 絞って述べた。私の考えではこれが GNU arch と CVS とを分かつ最も重 要で強力な性質だと考えるからだ。

もし君がエラい腕っぷしの強い男で、夜たまたま通りかかった路地 裏で三人の暴漢が君の理想のタイプを取り囲んでいる場面に出くわしたと したら、うれしくて泣きそうになるだろう。彼らだって同じなのだ。



[1] 実はここには君が現実的に彼らにそれを主張 できるかどうかという、もう一つの興味深い問題もあるのだが、そっちは この本の範囲外だ。

[2] 厳密に言うとブランチ側 リビジョン0 には「自分はトランクのリビジョン2から分岐されたリビジョ ンです」という内容を示すごく小さな追加の制御情報を持っているかも知 れない。後述するが、実際 GNU arch ではブランチ側にそのような情報を 持っているので、ツリーの内容はそのぶんだけわずかに異なっている。

第2章 インストール

「あたりまえのことを誰よりもあたりまえにやれ。それがあたりま えのことじゃないことがすぐにわかるから」- あるグル

インストールから始めよう。

インストール

一般的に言って、GNU arch のインストール時にはそれほど大きな 問題は起こらないのが普通だ。GNU arch は外部環境にほとんど依存しな いからだ。たとえば glibc のようなライブラリは利用せず、hackerlab という奇妙な名前の自前のライブラリを使ってシステムが構築されている。 本質的に外部に依存するのは、GNU tar, GNU diff, GNU patch のような プログラムで、これらのプログラムが古かったり GNU 互換ではないと不 具合が生じることはある。

GNU arch をインストールするにはまずは最新のソースコードを手 に入れる必要がある。公式なダウンロード先は以下の URL だ:

http://regexps.srparish.net/src/tla/

ここでは tla-1.2 を利用する。wget や curl のようなプログラ ムで取得する。

$ wget http://regexps.srparish.net/src/tla/tla-1.2.tar.gz
…
$

tla が GNU arch のコマンドとしての名前だ。何の略かという話に なるとTom Lord's Arch とか、Three Letter Acronym とか、いろいろ言 われる。深い意味はない。こジャレたウィットの解説を言った本人の口か ら聞くほど野暮なことはない。とにかく tla と言う。ソースコードを展 開すると、以下のようになる:

$ tar zxvf tla-1.2.tar.gz
…
$ cd tla-1.2
$ ls
=ARCH-USERS-README  =INSTALL  =RELEASE-ID  COPYING  configs  src  {arch}
$

普通の人であれば、おそらくこの時点で驚くだろう。こういうのが GNU arch の一番困ったところだ。これから楽しいバカンスに行こうとい うのに、家の前でいきなり車に引かれそうになる。ls の出力で '=' や' {','}'という文字を目にすることはそう多くはないが、普通のアルファベッ トと同じようにファイル名に利用できる文字とされており、GNU arch は 特殊なファイルを分別するのに、さまざまな場面で積極的にこのような文 字を利用するのだ。C 言語などを知っている人なら、識別子に対して '_' のような文字も含めて考えるだろう。このようなものだと思って割り切る のが一番良いようだ。

このような特殊文字の多用の是非については GNU arch メーリング リストで非常に頻繁に議論されてきた。メリットとしては、通常のバージョ ン管理対象となるファイルとの間に区別を設けることで特殊な処理をする 場合に便利であることをあげることができる。詳しくはインベントリとファ イルグループを議論する XXX で触れる。デメリットとしては、新規ユー ザを驚かせてしまい、学習曲線を不要に高くしてしまうこと、Unix のシェ ル上での補間機能がうまく効かない場合が出てくること、また他プラット フォームへの GNU arch の移植を困難にすること、などがあげられる。い ずれにせよ、ここではただ一言ですませる。つまり、「気にするな」だ。

いま展開した tla のディレクトリに戻って話を進めると、'='で始 まるファイルはいずれも普通のファイルだ。また {arch} はディレクトリ だ。ここではたまたまそうなっているが、'=' がかならず普通のファイル に利用されるとは限らない。ディレクトリであることもある。

実際のコンパイルは、=INSTALL ファイルに書いてあるとおり、src ディレクトリの下に =build というディレクトリを作ってからそこに移動 して実行する:

もう一度いう。'=' のような文字は気にするな。

$ cd src
$ ls
COPYING      Maintfile    PLUGIN       configure       docs-tla   links  {arch}
ChangeLog.d  Makefile.in  build-tools  docs-hackerlab  hackerlab  tla
$ mkdir =build
$ cd =build
$

通常のプログラムのインストールと同様、設定スクリプトの実行、 実際の構築、構築後のインストール、という 3 段階で進む。最後の段階 以外はすべてこの =build ディレクトリの中にしか書き込まない。インス トール前であれば =build ディレクトリを丸ごと消せば初期状態に戻る。

設定は以下のようにする

$ ../configure --prefix=/usr/local

Standard Configuration Settings:

    system = i686-pc-linux-gnu
    package =
    lord@emf.net--2004/dists--devo--1.0--patch-9(configs/emf.net-tla/devo.tla-1.2)
…
    src

configuring src...
$

--prefix オプションはインストールフェーズで実際に GNU arch をインストールする先になる。--prefix を省略すると、. /src/=build/=install がインストール先になるので、まだ GNU arch を あまり信用していない人はここにインストールして動作を試すこともでき る。気に入らなければひとつ上の =build ディレクトリからまるごと削除 すれば tar を展開した直後の状態に戻る。他の場所にはいっさい書き込 みをしない。現時点で GNU arch は単一のプログラムとして構築され、モ ノリシックなプログラム tla のみからなるので、インストール後そのま まコピーして別の場所に持っていっても動作する。(今後のバージョンで どうなるかは保証しない)。

--prefix オプションは通常は /usr/local にすると良い。これで /usr/local/bin に tla という名前のコマンドでインストールされる。間 違って /usr/local/bin と指定しないこと。これだと/usr/local/bin/bin にインストールされてしまう!

実際に構築する。長いメッセージが出力される。

$ make
set -e ; \
for dir in build-tools hackerlab links tla docs-tla; do \
	make -C $dir all ; \
done
make[1]: Entering directory `/home/octopus/tla-1.2/src/=build/build-tools'
set -e ; \
for dir in standards; do \
	make -C $dir all ; \

…

set -e ; \
for dir in src; do \
	make -C $dir all ; \
done
make[2]: Entering directory `/home/octopus/tla-1.2/src/=build/docs-tla/src'
make[2]: Nothing to be done for `all'.
make[2]: Leaving directory `/home/octopus/tla-1.2/src/=build/docs-tla/src'
make[1]: Leaving directory `/home/octopus/tla-1.2/src/=build/docs-tla'
$

最後にインストールする。

$ make install
set -e ; \
for dir in build-tools hackerlab links tla docs-tla; do \
	make -C $dir install ; \
done
make[1]: Entering directory `/home/octopus/tla-1.2/src/=build/build-tools'
set -e ; \
for dir in standards; do \
	make -C $dir install ; \

…

set -e ; \
for dir in src; do \
	make -C $dir install ; \
done
make[2]: Entering directory `/home/octopus/tla-1.2/src/=build/docs-tla/src'
make[2]: Nothing to be done for `install'.
make[2]: Leaving directory `/home/octopus/tla-1.2/src/=build/docs-tla/src'
make[1]: Leaving directory `/home/octopus/tla-1.2/src/=build/docs-tla'
$

実際に動作するかどうかは以下のコマンドで確認できる

$ tla help
                        tla sub-commands
                        ----------------

* help

                        help : provide help with arch


* User Commands

…

* Published Revisions Commands

                        grab : grab a published revision


* Miscellaneous Scripting Support

          parse-package-name : parse a package name
          valid-package-name : test a package name for validity


Use tla command -h for help on `command', or tla command -H for detailed help
$

かなりたくさんのコマンドがある。100近くもあるが、実際によく 利用するのは一握りだ。あとは実験的なコマンドであるか、GNU arch に 精通してからしか利用することはない。GNU arch のコマンドが多いのは、 単純なコマンドを組み合わせることによってさまざまな複雑な機能を実現 できるようになっているからだ。ちょうど Unix のツール群と同じ考え方 です。ひとつひとつのコマンドはゾウリムシみたいに単純だが、うまく組 み合わせると恐ろしくいろんなことができる。この考え方にはデメリット もある。実際の利用で、どのコマンドの後にどのコマンドを実行すればよ いか、あるいはどのコマンドとどのコマンドをどのように組み合わせれば 必要なひとまとまりの機能を実現できるか、がすぐにはわからないところ だ。つまり、典型的なワークフローがどんなものか、すぐには見えない。

このドキュメントではよく利用されるコマンドと、その利用の順序 についてグループ分けして説明していこうと思う。私の考えでは、ワーク フローの観点から見たとき、GNU arch には 3 個のグループに分けるのが いいと思う。

  • インストール後の必ずやる必要のある設定

  • バージョン管理対象を追加するたびに一度だけやる操 作

  • 日々の操作

この三つだ。

最初のグループは、GNU arch をインストールしたら必ずやらなく てはならない作業で、一度やれば二度以上やることは非常に稀なもの。二 つ目のグループは、新規に何かある特定のデータをバージョン管理しよう とするときの初期化処理、最後のグループは、初期化処理が済んだバージョ ン管理下にあるデータに対しておこなう日々の処理。この 3 番目のグルー プに属するコマンドは非常に少なく、せいぜい 5 個くらいだろう。

もちろん、GNU arch に慣れるにつれて残りのコマンドにも興味が わいてくるだろう。そのいくつかは処理を高速化したり、他の人のアーカ イブと協調して作業するのに必要だったり、GNU arch の根底を支える非 常に原始的な—そしてそれゆえ深遠な—コマンドであったりす る。詳しくは補遺のリファレンスを参照してほしい。一通り理解した後は リファレンス部分だけで話しが完結するような構成にしておいた。ここに はすべてのコマンドの一覧、書き込みの有無、典型的な例、CVS コマンド との対応、などについての記述がある。特に書き込みが全く発生しないコ マンドについては気軽に実行してその振る舞いを見ることができるだろう。 そして人によっては GNU arch の泥臭い実装の背後にある恐ろしく単純なデ ザインにおどろくかも知れない[3]

このドキュメントは GNU arch のあらゆるレベルのユーザに対して 役立つように書いたつもりだが、特にはじめて GNU arch を使おうと いう人の敷居をさげるのに役立てば、と思っている。

最初にやらなくてはならないこと

インストールが済んだ後、まずやらなくてはならないことが三つあ る。

  • UserIDの設定

  • アーカイブの作成

  • デフォルトアーカイブの設定

この三つだ。

UserIDの設定

GNU arch は分散型のバージョン管理システムであり、最終的に は別のアーカイブとのデータ交換が発生する。データ交換する際には自 分のアーカイブや後でのべるパッチログ、その他のデータが他の人のも のと区別するための識別子が必要になる。集中型のバージョン管理シス テムの場合、識別子はアーカイブのあるマシン上で一元的に生成するこ とができる。データ交換はあるマシン内で閉じており、マシン間でのデー タ授受は発生しないからだ。しかし分散型システムの場合、いまこのよ うに説明している時点でも地球上の別の場所にある別のマシン上で、新 しいアーカイブが設定されているかも知れない。それは誰であるかあら かじめ知ることはできないし、その人との間で重複しないような識別子 についての合意をとることもできない。誰ともあらかじめ合意せずに、 重複しない文字列を生成するためのなんらかの仕組みが必要にになる。

GNU arch の UserID はこのようなユニークな識別子を生成するため の仕組みの一つで、重複を避けるためにユーザの E-mail アドレスを使 う約束になっている。ある特定の E-mail アドレスを持っているのはそ のユーザただ一人であることが事実上保証されると考えられるからだ。

UserID は tla my-id コマンドを使って以下のように設定する:

$ tla my-id "foo bar <octopus@bluegate.org>"
$ tla my-id
foo bar <octopus@bluegate.org>
$

以下では、"foo bar" という名前の人間が、bluegate.org とい うマシン上に foo というアカウントを持っていて、ホームディレクト リは /home/foo, E-mail アドレスは octopus@bluegate.org であるとして 話を進める。

これで UserID が設定された。

アーカイブの作成

GNU arch で言うアーカイブとは、コンピュータ用語で一般に利 用される意味とは区別して考えたほうがいい。GNU arch の世界でいう アーカイブとは後で説明する基本的な管理対象単位である「バージョン」 を(一般的には)複数格納するための領域のことで、GNU arch のデータ オプジェクトの階層としては最上位に位置する記憶クラスだ。アーカイ ブは一つのコンピュータの上にも、別のコンピュータの上にもそれぞれ いくつでも作ることができるが、それぞれのアーカイブは当然別の名前 を持たなくてはならない。同じコンピュータの上に作った複数のアーカ イブは別のコンピュータの上にあるアーカイブ相互間の関係と同様、相 互に完全に独立している。アーカイブはアーカイブを作成したマシン上 のオペレーティングシステムが管理するどれかのファイルシステム上の 一つのディレクトリとして存在する。そして後述の「バージョン」はそ のサブディレクトリとして存在する。

GNU arch は分散型システムなので、たとえ君が他のマシンとの 間で今後いっさいデータの交換をしないとしても、アーカイブは作成時 点からあらかじめそのことを見越して作成しなければならない。つまり 他のアーカイブと区別できる名前をつけなければならない。しかも他の どの GNU arch ユーザと議論することなしに、だ。君がアーカイブを作 成したとたんに、すでにそのアーカイブは地球上の GNU arch 分散シス テムの一構成要素なのだ。あるいは潜在的にはいつでもそのようにみな すことができる状態に置かれるのだ。そう考えると理解しやすい。

アーカイブの作成はアーカイブ用ディレクトリの作成と、実際の アーカイブの作成の二段階にわかれる。

$ pwd
/home/octopus
$ ls
Maildir  tla-1.2  tla-1.2.tar.gz
$ mkdir ARCHIVES
$ ls
ARCHIVES  Maildir  tla-1.2  tla-1.2.tar.gz
$ tla make-archive octopus@bluegate.org--2004 \
    /home/foo/ARCHIVES/octopus@bluegate.org--2004
$ tla archives
octopus@bluegate.org--2004
    /home/foo/ARCHIVES/octopus@bluegate.org--2004
$

アーカイブはファイルシステム中のどこに作成しても良い。が、 GNU arch を利用するユーザアカウントのホームディレクトリに作るの が普通だし、自然だろう。他のユーザとの間で特にアーカイブを共有す る積極的な理由がある場合は /usr/local のような場所に作ることもで きるが、GNU arch はアーカイブ間でデータの交換をすることが できるので、ユーザごとに自分のホームディレクトリに自分専用のアー カイブを作る方が利用しやすいかも知れない。ここではユーザのホーム ディレクトリ配下に作成することにする。

アーカイブをホームディレクトリに直接作ることもできるが、そ れだと新しいアーカイブを作るたびにホームディレクトリにアーカイブ 用ディレクトリが追加され、アーカイブ用サブディレクトリで一杯になっ てしまう。これはあまり楽しい状況ではないので普通はアーカイブ専用 のサブディレクトリを作成し、その中に実際のアーカイブを作るように するのが慣例だ。これを便宜的にアーカイブフォルダと呼んでおく。

アーカイブフォルダの名前にも特に約束ごとはないが、非常に重 要なディレクトリであることだけは確かだ。まちがってアーカイブフォ ルダを削除してしまうと、GNU arch で保管してきた一切のデータが消 えてしまう。だから重要であることを示す特徴的な名前をつけると良い。 今回は単に ARCHIVES という名前にした。

人によっては、{archives}という特殊な名前をつけるのを推奨す る人もいる。この方式の利点は、1.奇妙な名前なので間違った操作でアー カイブフォルダを削除してしまう危険が減る、2. '{' 文字でファイル 名を始めると ls コマンドでディレクトリの一覧を表示する際にこのディ レクトリの表示が一番最後の方にくる、ということがある。欠点は、す でに書いたように、1.シェルの補完機能がうまく働かなくなることがあ る、2.どうも馴染めない、3.シェルスクリプトで ${foo} のような記述 と衝突する可能性があるのではないか? 4.どうも馴染めない、などがあ る。好みに応じて名称を選択してほしい。

実際にアーカイブを作るには make-archive コマンドを実行する。 このコマンドで今回 ARCHIVES というディレクトリの中に作った実際の アーカイブがoctopus@bluegate.org--2004 だ。アーカイブ名にも命名 規約があるがUserIDとは全く独立している。アーカイブ名の正確な命名 規約は補遺を見て欲しいが、大雑把に言うと、e-mail アドレスの雰囲 気を持った文字列が先頭に来て、その後ハイフンが二つ来たあとにアル ファベットや数字やハイフンが来る、というものだ。--2004 の部分は 省略してemailアドレスだけでも良い。

アーカイブ名の一意性は、UserIDよりも重要なものだ。UserIDの 時と同じように自分の E-mail アドレスを利用するか、uuid の方法を 使えば一意性は確保できるだろう。

アーカイブ名は論理的な名前であり、それがファイルシステム上 のどの場所に具体的に結びつけられるかを示すのがアーカイブ位置だ。 これをすでに作ったアーカイブフォルダの中に指定する。アーカイブ位 置のファイル名部分はアーカイブ名とは独立に指定できるが、後で混乱 が減るように、私は合わせるのが好きだ。上の例ではそのようにしてあ る。結果、ファイル名称として '@' のついたファイル(正確にはディレ クトリ)がシステムにできてしまった。これは奇妙な文字が嫌いな私が あえて奇妙な文字を利用する数少ない場面のひとつだ。

tla archives コマンドは GNU arch システムに登録されている アーカイブ名とその位置を一覧表示するコマンドだ。確かに今作ったアー カイブができているのがわかる。アーカイブの登録情報は、内部的には ~/.arch-params/=locations というディレクトリに格納されている(ま た '=' 文字だ :)。直接編集することはないが、興味のある人は理解を 深めるためにちらっと覗いてみるのも良いだろう。

デフォルトアーカイブの設定

GNU arch の多くのコマンドはデフォルトアーカイブに対して実 行される。これはちょうと Unix のコマンドの多くがカレントディレク トリに対して実行されるのと同じような発想だ。すでに見たようにアー カイブ名は非常に長いのでデフォルトアーカイブを設定しておくとよい。 いま作ったアーカイブを my-default-archive コマンドでデフォルトアー カイブとしよう:

$ tla my-default-archive octopus@bluegate.org--2004
$ tla my-default-archive
octopus@bluegate.org--2004
$

このコマンドは引数なしで実行すると現在のデフォルトアーカイ ブの内容が表示される。以降の章ではデフォルトアーカイブが設定 されていることが前提となるので注意してほしい。

三つの困難

GNU arch の抱える三つの問題は、[1]奇妙な文字の問題、 [2]長いファイル名の問題(-- の問題含む)、[3]ファイル判別ロジックの 複雑さ、である。これをもっと詳しく。

この章のまとめ

この章では GNU arch のインストールの仕方と、インストール後最 初にしなくてはならない設定について説明した。環境設定に関していくつ かの名前が出て来た。UserID, uid, アーカイブフォルダ、アーカイブ名、 アーカイブ位置名。これらはいずれも必要に応じて命名規約を満たしさえ すれば任意に指定できるが、できるだけ統一したほうが混乱が少なくて済 むことを説明した。

次の章では新しいアーカイブバージョンを作成する方法について説 明する。



[3] し、もちろんしないか も知れない。

第3章 バージョンの作成

前の章では、GNU arch インストール後に行なう GNU arch システ ム全体に関する設定をした。ここまでくればいつでも新しいバージョンを アーカイブに追加し、具体的なバージョン管理を始めることができる。こ の章ではまず GNU arch の世界でのアーカイブ、バージョン、リビジョン、 などの言葉を正確に定義する。その上でテスト的なバージョンを作り、実 際のファイルをバージョン管理下に置くための最初のデータ取り込み処理 をする。これを初期インポートを行う。バージョンの作成は簡単だが、イ ンポートではつまづくかも知れない。インポートしようとするファイルの 性質によっては GNU arch がソースファイルとして認識しないことがある ためだ。ソースファイルを認識させるためには GNU arch のソースファイ ルの判別ロジックについての理解が必要になる。ここではあまり細部に立 ち入らないように注意して、ファイル判別ロジックの概要を説明し、初期 インポートすることにする。ファイル判別ロジックの詳細は、インベント リの概念とも密接に関連し、非常に複雑なので、章をわけて説明しようと 思う。

GNU arch を利用する上でおそらく一番大きな障害の一つが、この ファイル判別ロジックだ。あとは、名前空間の複雑さ、奇妙な文字の多様、 と続く。GNU arch の根底にあるデザインは非常に単純なので、このよう な複雑さがあるのは残念なことだ。

この章では、他のアーカイブとのやりとりについての説明は避け、 つまり君は自分だけで利用するデータを自分だけで管理している、そんな 状況に話を絞った。他の人がそのデータに対してかかわってくることはな い。君は必要に応じて自分のデータを修正し、区切りがついたところで新 しいリビジョンを作る。リビジョンは時間の経過とともにどんどん増えて いくが、枝分かれしたりすることはない。時間の方向に一列に並んでいる 一本のラインだ。GNU arch が力を発揮するのは他のアーカイブのほかの バージョンとの間で分岐したりマージしたりする場面なのだが、そのよう な場合でもここでの操作が基本になる。

前提となる環境

この章では前の章の設定が済んでいると仮定する。つまり:

  • 君は octopus というアカウントを持ち、今そのホー ムディレクトリにいる。

  • ホーム ディレクトリの名前は /home/octopus である。

  • tla が無事インストールされて利用できる状態にある。

  • tla my-id コマンドで UserIDが 正しく設定されている。

  • /home/octopus/ARCHIVES という名前のアーカイブフォ ルダが作成されている。

  • octopus@bluegate.org--2004 という名前のアーカイ ブが作成されている。

  • そのアー カイブ位置は/home/octopus/ARCHIVES/octopus@bluegate.org--2004 で ある。

  • octopus@bluegate.org--2004 は君のデフォルトアー カイブとして設定されている。

以上の前提が成り立たない限り以下の説明は少なくともそのままで は動作しないので注意してほしい。厳密にこの環境を作りあげることがで きないのは明らかだろう。自分用のメールアドレスを設定したり、ホーム ディレクトリの名前が違っている場合には適宜自分の環境にふさわしい形 に読みかえてほしい。

バージョンとは何か

さて、アーカイブを作ってはみたものの、まだそこには何も存在し ていない。空っぽである。これからこの中に GNU arch での最も基本的な 管理単位である「バージョン」を作ってみようと思う。これ には tla setup-archive コマンドを使う:

$ ls
ARCHIVES  Maildir  tla-1.2  tla-1.2.tar.gz
$ tla archive-setup test--proj--1.0
* creating category octopus@bluegate.org--2004/test
* creating branch octopus@bluegate.org--2004/test--proj
* creating version octopus@bluegate.org--2004/test--proj--1.0
$

バージョン」とは、他のバージョン管理システムで は「リポジトリ」と呼ばれるものにあたる。バージョンの中 に初期データをインポートし、その後データを修正してはコミットを繰り 返すことで、時間と共にデータがバージョンに蓄積されていく。ある1時 点でのバージョンの内容をリビジョンと言う。バージョンはリビジョンの 集まりで、それぞれのリビジョンは作られた時間によって順序づけされて いる。リビジョンにゼロから始まる番号をつけて、この番号によって特定 のリビジョンを指定することができる。これをリビジョン番号と言う。リ ビジョンはまた自分の性質に応じた名前をもっている。これをリビジョン 名と言う。通常最初のリビジョン名は base-0 だ。それ以降のリビジョン 名は普通 patch-n という名前になる。ここで n は 1 から順番に増えて いく整数でリビジョン番号と呼ばれる。

バージョンという言葉の日常的使い方から連想されるものはリビジョ ンに近いことに注意しよう。たとえば「XYZ ソフトウェアのバージョン1 がバージョンアップして バージョン 2 になりました。どうぞお買い求め ください」というときの「バージョン」は、GNU arch でいう「リビジョ ン」の意味に近く、「XYZ ソフトウェア」が、GNU arch でいう「バージョ ン」に近い。「リビジョン」という言葉のこういう使い方は GNU arch に 限らずモダンなバージョン管理システムではほぼ共通に使われている。 「バージョン」という言葉のほうは他のシステムでは「リポジトリ」と呼 ばれることが多いが、要するに「リビジョン全部」をまとめたもののこと を指す。

いま作ったバージョンは、test--proj--1.0 という名前だ。GNU arch ではこのようにバージョン名は三つの単語を '--' でつないだ名前 にしなくてはならないという規約がある。三つの部分を先頭から「 カテゴリ名」、「ブランチ名」、「バージョン名 」と言う。バージョンが、カテゴリ名、ブランチ名、バージョン名 の三つの文字列の組み合わせで構成されていることには、論理的な必然性 はまったくない。また、それぞれの名前から連想されるような名前間の制 約や階層構造があるわけでもない。単に 「第一名称部」、 「第二名称部」、「第三名称部」と考えて問題な い。これらの名称に深い意味はなにもない。

今後バージョンに関する一般的な議論の時、バージョンを指すのに シンボリックに C--B--V と記述することがある。C, B, V はもちろんそ れぞれの名前の頭文字だ[4]。 複数のバージョンを使った議論では、C1--B1--V1, C2--B2--V2, … のようにしていくつかのバージョンを示すこともある。「バージョ ン」と「バージョン名」の違いに注意してほしい。GNU arch の一部のドキュメントではこの区別があいまいなものもあるが、文 脈に応じてどちらの意味かを判断してほしい。

バージョン、という言葉の日常的な意味からは、異なるバージョン との間の関連を連想してしまうかも知れない。たとえばtest--proj--1.1 という名前の別のバージョンを作ることもできる、この場合、 test--proj--1.0 と test--proj--1.1 との間に、何か意味的につながり が生ずるのではないか、と。しかし、この両者はまったく別のバージョン、 他のバージョン管理システムの言葉で言うと、まったく別のリポジトリだ。 異なるバージョン間を「継続」という機能を使って関連づけ ることはできるし、それが似た名前のバージョンであったほうが人間にとっ ては都合が良いかも知れない。しかし、test--proj--1.0の継続を test--proj--1.1 とするかわりに、ergo--sum--100.0という名前のバージョ ンを作って継続し、test--proj--1.1 をまったく別の目的に利用すること も、そもそもそのようなバージョンを作成しないこともできる。継続につ いては別の章で詳しく議論する。

バージョンは必ず、どこかのアーカイブ中に作成される。今の場合 だと octopus@bluegate.org--2004 という名前のアーカイブだ。tla archive-setup コマンドで、これを明示的に指定する引数はなかったが、 これはデフォルトアーカイブを octopus@bluegate.org--2004 にあらかじめ設 定しておいたからだ。いまはまだ一つのアーカイブしかないが、複数のアー カイブが存在して、デフォルトアーカイブ以外のアーカイブにバージョン を作成したい場合には -A というオプションを使って明示的に作成先を指 定することもできる。バージョンは指定されたアーカイブ中にできるだろ う。-A オプションは tla archive-setup コマンドに限らず、アーカイブ の指定が必要なすべての tla コマンドで指定することができるオプショ ンだ。そのようなコマンドで -A オプションを省略するといつでもデフォ ルトアーカイブが指定されたものと見なされる。

同じ名前のバージョンを別のアーカイブに作成することもできる。 その場合、C--B--V だけを指定しても両者を区別することができない。こ の場合、アーカイブ名をつけて、 octopus@bluegate.org--2004/test--proj--1.0のように表現する決まりがある。 この表現を使うと、ある特定のバージョンが完全に定まる。これは一つの マシン上に限ったことではない。アーカイブ名はE-mail アドレスを含ん でいるので、地球上のすべてのマシンを考慮しても一意に定まる。 octopus@bluegate.org--2004/test--proj--1.0 は、君のマシン上にある、地 球上で唯一ここだけにあるバージョンだ。[5]後の章で、バージョン間でデータの交換をしなくては ならない場合に、この一意性が大切になる。このように A/C--B--V の形 で指定したバージョンを、完全に修飾されたバージョン名、と言う。

アーカイブと、バージョンの関係を絵に書いてみる。すでに注意し たように、カテゴリ名とブランチ名は、バージョンの階層構造にはまった く関係しない概念だ。つまり:

図 3.1. まちがったバージョンの階層構造

まちがったバージョンの階層構造

ではなくて:

図 3.2. 正しいバージョンの階層構造

正しいバージョンの階層構造

のようにイメージしてほしい。地球上の無数のマシンの上に、異な る名前のついた無数のアーカイブがあり、その中にさまざまなバージョン が存在している。octopus@bluegate.org--2004 と、 bar@bogus.example.com--2003、上には、同じ名前のバージョン festina--lente--1.0 がある。これはたまたまそうなったのかも知れない し、二人のハッカーが関連するバージョンを表すのにお互いにわざと同じ 名前を取り決めたのかも知れない。いずれにせよ、同じ名前のバージョン が別のアーカイブにあっても、地球上の GNU arch 分散システムが混乱す ることはない。別のディレクトリにある二つの readme.txt ファイルが何 の関係もないのと同じことだ。

図 3.3. バージョン同士の関係

バージョン同士の関係

ふたつのバージョンは、同じアーカイブ内にあろうがなかろうが、 別のアーカイブ内にある場合、その二つのアーカイブが同一マシンにある かどうかには全くかかわらず、対等な関係にある。後の章でアーカイブ間 の分岐やマージについて説明するが、このような特殊な関係にある二つの バージョンは、それぞれどのアーカイブの上にあっても同じように動作す る。同じアーカイブ上になければできないような処理はない [6]

さてあるアーカイブ中にどのようなバージョンがあるかは tla abrowse で確認することができる:

$ tla abrowse
octopus@bluegate.org--2004
  test
    test--proj
      test--proj--1.0

$

このコマンドも明示的にアーカイブを指定しなければ、デフォルト アーカイブに対して処理される。確かに今作ったバージョンが存在して いる。

準備は整った。次の節では、このバージョンに対して実際にデータ をインポートしてみる。何か新しいことを始めるとき—それは誰も 挑戦したことのない問題を解くためのプログラムかも知れないし、歴史の 本を書くことかも知れない—最初にやることになるのが、次の節で の議論だ。

初期データのインポート

GNU arch の初期インポートの典型的なユースケースは三種類ある。

  • フルスクラッチから作ったソースコードを新規に GNU arch で管理していく場合

  • 別の管 理方法で既にパブリック管理されているソースコードを GNU arch で管 理しようとする場合

  • 既に GNU arch で管理されているバージョンから分岐を作る場合

以下では最初の利用方法について説明する。二番目については次章 のインベントリの議論を通じて説明し、最後のものは分岐の章で説明しよ うと思う。初期設定に関してだけ言えば、二番目のケースが一番面倒で、 最後のものは一番簡単だ。

概論

バージョンを作ったら、あとは初期データをそこにインポートす るだけだ。「インポート」とは、これまでバージョン管理下 になかったひとまとまりのデータを、最初にバージョンに格納することだ。 このひとまとまりのデータは、全体としてひとつのディレクトリにまとめ られていなければならない。格納したいデータの一部があるディレクトリ にあり、残りのデータがそれとは親子関係のないディレクトリにあるよう な場合、そのままの形ではインポートすることはできない。このような場 合は管理対象の単位をそれぞれに分割するか、新しいディレクトリの中に 両者のコピーを作り、それをインポートする必要がある。このようにして まとめたデータの最上位のディレクトリをツリーのルートと言い、この領 域全体をツリーと言う。

ツリーの中にはどのような名前のファイルを置くこともできるし、 またそれらがどのようなファイル形式であっても良い。ファイル形式は非 常に大きくテキストファイルとそれ以外のバイナリファイルに区別できる ことはすでに述べた。そこでバージョン管理対象として差分管理をする場 合にはテキストファイルが向いているという話をしたが、GNU arch の場 合、バイナリファイルも管理することができる。ただしこれはとにかく管 理することはできる、といった程度の話であって、バイナリファイルに対 しては GNU arch は特に優れた性能を発揮するわけではない。たとえばこ れもすでに述べたことだが、バイナリファイルを管理する場合、リビジョ ン間の差分を人間に理解可能な形で直観的に示すことはできない。できる ことは現在または過去の指定されたリビジョンのバイナリファイルをその まま取り出すことだけだ。

GNU arch でバイナリファイルを管理するのは、大部分がテキスト ファイルだが、その一部がテキストファイルに付随したバイナリファイル であるような場合が多い。たとえば君が編集している HTML ファイルがあ るドキュメントルート配下を GNU arch で管理しつつ、HTML ファイルが 参照する一部のアイコンや小さな画像などを同時に管理対象としたいよう な場合が考えられる。あるいは、このドキュメント自身を考えてみてほし い。このドキュメント自身、何を隠そう tez@kamihira.com--2004s/Book--GNU-arch--0.0.1というバージョンで管 理される立派なアーカイブだ。この中身はと言えば、ほとんどが XML 文 書、つまりはテキストファイルで、文書中に現れる画像は OpenOffice の Impress というバイナリファイルから生成した png 形式のバイナリファ イルだ。両方とも Book--GNU-arch--0.0.1 の一部としてバージョン管理 されている。

ツリーの中のすべてのファイルとディレクトリがバージョン管理対 象下に置かれるわけではない。もちろんそうすることもできるが、実際に は管理したくないファイルやディレクトリが混じっていることがよくある。 たとえば、C 言語の開発をしていて、ディレクトリにいくつかファイルが ある場合、コンパイルの中間結果の *.o のような形のファイルや、エディ タのバックアップファイルなどはバージョン管理したくはないだろう [7]。あるいは 自分専用のメモ書きファイルのようなものがツリー中に含まれていてその ファイルについては広く公開したくないこともあるかも知れない。インポー トする前には、どのファイルをバージョン管理下におき、どれをバージョ ン管理外にするかをあらかじめ指定する必要がある。

GNU arch ではこの指定をするには、まずは管理対象とするツリー を tla init コマンドを利用して、GNU arch 管理可能なプロジェクトツ リーの形に変えなくてはならない。プロジェクトツリーとは、GNU arch の管理領域用のディレクトリ{arch} を最上位に含むようなツリーのこと だが[8]、この {arch}ディレクトリ中の設定ファイル、 =tagging-method[9]の内容によって指定するた めだ。tla init コマンドは {arch} 管理領域をツリーのルートに追加す る以外のことは一切しない。

利用するサンプルプログラム

さて、そろそろ、何か良いデータのサンプルが必要になる。GNU arch はどのような種類のデータも管理することができるが、やはりプ ログラム言語のソースコードを管理することが多いので、C 言語のプロ ジェクトで説明しようと思う。複数のファイルを管理できることと、サ ブディレクトリも管理できることを示すため、四つのファイルからなる プロジェクトを考えることにする[10]。このプロジェクトは 4 っつの 通常ファイルと、それらを編成するための二つのサブディレクトリから なっている。以下のようなものだ。

$ pwd
/home/octopus/proj
$ find
.
./lib
./lib/tools.c
./inc
./inc/tools.h
./main.c
./cc.sh
$

main.c は tools.c にある関数を呼び出している。

$ cat main.c
#include "./inc/tools.h"

int main()
{
        hello_world();

        return (0);
}
$

呼び出される側の lib/tools.c は printf() で文字列を表示する だけだ。

$ cat lib/tools.c
#include <stdio.h>

void hello_world()
{
        printf("hello world\n");
}
$

lib/tools.c のプロトタイプ宣言は inc/tools.h にある:

$ cat inc/tools.h
void hello_world();
$

コンパイルは cc.sh という小さなスクリプトで行う。

$ cat cc.sh
#!/bin/sh

cc -o hw main.c lib/tools.c
$

とても単純だ。先に進む前にプログラムが本当に動作するかどう か確認しておこう。いまの例をエディタで実際に作成した場合には、 cc.sh を実行可能とすることに注意してほしい。その後、コンパイルし、 実行を確認する。

$ chmod +x cc.sh
$ ./cc.sh
$ ls
cc.sh  hw  inc	lib  main.c  {arch}
$ ./hw
hello world
$ 

コンパイルによって hw という実行ファイルが作成された。確かに 動作している。

初期インポート作業(1) - tla init-tree

では話を戻して、このディレクトリを、プロジェクトツリーに変え、デフォル トバージョンを前の節で作っておいた test--proj--1.0 に設定する。 これには tla init-tree を使う:

$ ls
cc.sh  inc  lib  main.c
$ tla init-tree test--proj--1.0
$ ls
cc.sh  inc  lib  main.c  {arch}
$ tla tree-version
octopus@bluegate.org--2004/test--proj--1.0
$

{arch}という管理用のサブディレクトリができた。tla tree-version はデフォルトバージョンを表示するためのコマンドだ。確 かに test--proj--1.0 になっている。tla init-tree コマンドはアーカ イブの領域に対しては何も変更していない—参照すらしていない —ことに注意してほしい。このコマンドはあくまでもいま作ったプ ロジェクトツリーが、デフォルトで test--proj--1.0 バージョンに関連 づいていることを指定しただけだ。

初期インポート作業(2) - tla id-tagging-method

tla init-tree を済ませたら、IDタグづけの方法を選択しなくて はならない。IDタグづけの方法については次章で詳しく説明するが、プ ロジェクトツリー中のどのファイルをバージョン管理対象とみなしどれ をそうみなさないかを決める方式のことだ。これには name, tagline, explicit の三種類がある[11]現在の IDタグづけの方法を表示す るには引数なしでこのコマンドを実行する:

$ tla id-tagging-method
explicit
$ 

explicit になっている。ここでは説明のために最も簡単なnames の方式に設定することにする。設定する場合には引数で指定すればよい:

$ tla id-tagging-method names
method set: names
$ tla id-tagging-method
names
$ 

これで names になった。

初期インポート作業(3) - インポートファイルの確認

IDタグづけの方法の設定が済んだら tla inventory コマンドを 使って実際のインポート対象となるファイルを確認する:

$ tla inventory
S  cc.sh
S  hw
S  inc/tools.h
S  lib/tools.c
S  main.c
$ 

S という文字はソースファイル、つまりバージョン管理対象とな るファイルを意味する記号である。この他にも P,B,J,T,U で表される 状態がある。それぞれ、プレシャス、バックアップ、ジャンク、ツリー、 アンリコグナイズ(非認識)の意味だ。詳しくは次章で説明する。

上記の一覧の中で、hw というファイルがソースファイルだと認 識されているが、これはコンパイルの結果できたファイルであり、管理 対象としなくはない。ファイルを管理対象外とするには {arch}/=tagging-method というファイルを編集し、exclude で始まる 行の内容を調整する。{arch}/=tagging-method という文字列の並びは 何度見ても気持が悪いかも知れないが、れっきとした普通のファイルで ある。vi を使っているなら:

$ vi {arch}/=tagging-method

emacs を使っているなら:

$ emacs {arch}/=tagging-method

でうまく編集できるはずだ。試してみてほしい。このファイル中、 exclude で始まる行があるはずだ。私の環境では以下のようになってい た:

exclude ^(.arch-ids|\{arch\}|\.arch-inventory)$

これは正規表現という決まりにしたがって記述された行で、「. arch-ids または {arch} または .arch-inventory という名前のファイ ルはソースファイルから除外してください」という意味になる。正規表 現についてあまり詳しくない人は、GNU arch で利用するための最低限 度の説明を補遺にしておいたので読んでみてほしい。しかし、カンが働 く人なら正規表現を知らなくても、hw を除外するにはどうしたらよい か、あたりをつけることはできるだろう。そう、以下のようにしてやれ ばよいのだ:

exclude ^(hw|.arch-ids|\{arch\}|\.arch-inventory)$

先頭のほうに、"hw|" という文字列を追加したのがわかる。これ でファイル保存でエディタを抜け、もう一度 tla inventory コマンド の出力を見てみよう:

$ tla inventory
S  cc.sh
S  inc/tools.h
S  lib/tools.c
S  main.c
$ 

hw がいなくなってくれた。ソースファイルから除外されたのだ。 これでインポートの準備がやっと整った。=tagging-method ファイルを 編集して気がついたと思うのだが、このファイル中には exclude 行の 他にもいろいろと怪しいことが書かれている。このあたりについても次 章でじっくり説明するので楽しみにしていてほしい。

初期インポート作業(4) - インポート

おまたせしました、と心から言いたい気分だ。どうして使い始め からこんなに複雑なのだろう。たかがバージョン管理システムだろう。 俺にとってはただの手段でしかないんだ。こむつかしいこといいなさん な、こっちはとっとと使いたいだけなんだよ、と。そう感じているなら、 たぶんあなたは正常な人間だ。でも忍耐もここまでだ。インポート処理 自体は、まるでアレキサンダー大王の最後みたいにあっけない。

$ tla import
* imported octopus@bluegate.org--2004/test--proj--1.0
$ 

あまりにあっけなくて本当にインポートできたかどうか不安にな る。確認する方法はいくつかある。まずは、アーカイブ全体のようすを ざっと見るための tla abrowse コマンドを実行すること。

$ tla abrowse
octopus@bluegate.org--2004
  test
    test--proj
      test--proj--1.0
        base-0

$ 

base-0 という表示があるだろう。これは最初のリビジョンの名 前だ。確かに作成されているようだ。余談になるが abrowse コマンド 出力が、カテゴリ名、ブランチ名、バージョン名のような階層構造っぽ く表示されているのにだまされないでほしい。すでに言ったように、実 際にはこれらの間に強い階層構造はない。

tla abrowse コマンドの出力でも安心できない場合には、実際に アーカイブ中の base-0 リビジョンを今のプロジェクトツリーとは別の 場所に取り出してみればよい。これには以下のように tla get コマン ドを使う:

$ pwd
/home/octopus/proj
$ cd ..
$ ls
ARCHIVES  proj	tla-1.2  tla-1.2.tar.gz
$ tla get test--proj--1.0 hogehoge
* from pristine cache: octopus@bluegate.org--2004/test--proj--1.0--base-0
* making pristine copy
* tree version set octopus@bluegate.org--2004/test--proj--1.0
$ ls
ARCHIVES  hogehoge  proj  tla-1.2  tla-1.2.tar.gz
$ cd hogehoge
$ ls
cc.sh  hw  inc	lib  main.c  {arch}
$ 

ホームディレクトリに戻って、hogehoge というディレクトリに base-0 リビジョンを展開してみた。やはりうまくインポートできてい るようだ。でなければうまく取り出せるわけがない。納得できたら hogehogeを消しておこう。せっかく get コマンドが出てきたので少し 補足するが、get コマンドを最後の引数なしで実行してみよう。

$ pwd
/home/octopus/hogehoge
$ cd ..
$ ls
ARCHIVES  hogehoge  proj  tla-1.2  tla-1.2.tar.gz
$ rm -rf hogehoge
$ tla get test--proj--1.0
* from pristine cache: octopus@bluegate.org--2004/test--proj--1.0--base-0
* making pristine copy
* tree version set octopus@bluegate.org--2004/test--proj--1.0
$ ls
ARCHIVES  proj	test--proj--1.0--base-0  tla-1.2  tla-1.2.tar.gz
$ tla get test--proj--1.0
get: output directory already exists (/home/octopus/test--proj--1.0--base-0)
$ 

言いたいことはこうだ。展開先ディレクトリを指定しないと、 tla get は バージョンにリビジョン名をつなげたような名前のサブディ レクトリ—いまの場合だとtest--proj--1.0--base-0—を作っ てそこにリビジョン内容を展開すること、展開しようとするディレクト リがすでに存在する場合にはそれを上書きすることはないということ。 展開先ディレクトリは必ず新しく作成されなくてはならない、というこ と。確認したらディレクトリを消しておこう。

$ ls
ARCHIVES  proj	test--proj--1.0--base-0  tla-1.2  tla-1.2.tar.gz
$ rm -rf test--proj--1.0--base-0
$ ls
ARCHIVES  proj	tla-1.2  tla-1.2.tar.gz
$ 

もう信じてもいいだろう。我々は確かに base-0 という最初のリ ビジョンを手に入れたのだ。プロジェクトツリーとアーカイブの様子を 図で示すと以下のような感じになっている。

図 3.4. プロジェクトツリーとアーカイブ

プロジェクトツリーとアーカイブ

プロジェクトツリー(今の場合 /home/octopus/proj)を削除して もアーカイブ中にできた base-0 は影響を受けないことに注意しよう。 プロジェクトツリーとは君が汗を流し、呻き、額を打ちつけ、格闘しつ づける、おがくずと鉄の切りくずが散らかる、油の匂が漂う泥くさい 「作業場」なのだ。あとで君のアーカイブからしみ一つない理路整然と したソースファイルを tla get で取り出した人間には、君のそんな姿 などおそらく想像もつかないだろう。だがそれでいいのだ。それが本当 の美学なのだから。

リビジョンとは何か

前節で最初のリビジョンをバージョン test--proj--1.0の中に作っ た。ここからはプロジェクトツリーに対して変更を加えてはコミットを発 行することで、リビジョンが増えていく。ここではリビジョンという言葉 について少し詳しく説明する。

バージョンはゼロ個以上のリビジョンを格納する場所で、アーカイ ブの中にある。バージョンにできる最初のリビジョンは base-0 という名 前になる。二つ目以降のリビジョン名は patch-n という形になる。ただ しn はコミットの順序を示す1から始まる整数である。[12]

一度作成されたリビジョンは、修正されたり、削除されることはな い。リビジョンはバージョンの中にあり、バージョンはアーカイブの中に あり、アーカイブはその性質上既存データに対する修正はありえないので、 リビジョンを作成するのに利用したプロジェクトツリーを削除しても一度 コミットしたリビジョンは削除されることはない。リビジョンはバージョ ンの中で順序を持っている。つまり、コミットした時間の順序に一列に並 べることができる。リビジョンをこの順序に並べ、先頭のbase-0 を 0 番 目として数えていった番号のことをリビジョン番号と呼ぶ。リビジョン名 を指定すると、そのリビジョン番号がひとつ決まる。逆にリビジョン番号 を指定するとそれに対応したリビジョン名が求まる。この意味で両者を同 一視することができる。リビジョン名は、パッチレベルと呼ばれることが あるが、リビジョン番号を指す場合もあるのでどちらの意味で利用されて いるか文脈から判断する必要がある。リビジョン番号とリビジョン名の対 応は以下のようになる:

0    base-0
1    patch-1
2    patch-2
…

リビジョン名は文脈によって二つの異る意味をもつ。リビジョン名 は、そのリビジョンをコミットしたプロジェクトツリーの状態を示すと同 時に、直前のリビジョンとの間の差分であるすチェンジセットをも意味す る。その場合、このチェンジセットは直前のリビジョンといま問題になっ ているリビジョンの両方に対して等しく関係しているにもかかわらず、後 の方のリビジョン名によってこのチェンジセットを参照することに注意し なくてはならない。

プロジェクトツリーとは何か

プロジェクトツリーとは、tla init-tree コマンド、あるいは tla get コマンドなどによって作成された {arch}管理領域を持つディ レクトリツリーのことである。プロジェクトツリーはリビジョンとは違っ て一つ以上のバージョンと関係を持つことができる。しかし通常は主に 一つのバージョンと関係するだけのことが多いし、またこれで十分であ る。プロジェクトツリーはデフォルトバージョンを設定することができ る。プロジェクトツリーに対してはたらく多くのコマンドは特に指定し なければデフォルトバージョンに対してはたらく。

プロジェクトツリーは、通常はデフォルトバージョンに対して行 なうコミットを、実は任意のバージョンに対して実行することができる。 あるバージョンに対するコミットが成功するには、アーカイブ中にある そのバージョンに含まれるすべてのリビジョンのパッチログを、そのプ ロジェクトツリーは持っていなくてはならない。この条件が満たされた 時、そのバージョンの最新リビジョンとプロジェクトツリーとの間のチェ ンジセットが計算され、その内容によって新しいリビジョンがそのバー ジョンに追加される。両者のツリーの内容がいかに違っていたとしても、 チェンジセットの差分の計算は(適用の計算と違って)常に成功するので、 かならず新しいリビジョンを追加することができる。

あまり頻繁に起こる状況ではないが、プロジェクトツリーの内容 をあるバージョンの最新リビジョンとして強制的にコミットしたい場合 には、tla sync-tree を使って、該当バージョンのすべてのリビジョン のパッチログをプロジェクトツリーに追加すれば良い。sync-tree はあ る意味、コミットロジックをだますためのコマンドであるとも言える。

同じような視点でプロジェクトツリーの update を述 べよ

日々の利用

概論

ようやく初期インポートが終わった。ここから先は単純だ。どんな バージョン管理システムでも、基本的な操作はたった二つしかない。それ は:

  • プロジェクトツリーのファイルに修正を加えて

  • それをコミットする

これだけだ。この二つの操作を基本とした上で、じゃあ他のアーカ イブのデータを取り込むことができるのか、二人以上の人間が同じ場所に 変更したときうまく調停してくれるか、ネットワークをまたいでマージで きるか、複数のファイルの変更をひとまとまりの変更としてまとめて取り 扱ってくれるか、ドキュメントは充実しているか、サポートセンターはあ るか、ロゴ入りマークのTシャツと携帯ストラップは扱っているか、作者 はヤンキースファンであるかどうか、などの話が続く。

最初の操作。つまりプロジェクトツリーのファイルに対する修正は、 GNU arch とは無関係に行う処理になる。テキストファイルであればエディ タを使って修正するかも知れないし、一括置換用のスクリプトを流してバッ チ的に多くのファイルを変更するかも知れない。バイナリファイルであれ ば、たとえば画像ファイルならその画像を編集するためのお絵かきソフト か何かで編集してから保存する。どんな修正をしようと君の勝手だし、こ こが大切なところなのだが、GNU arch はそれらの修正に対して一切口を 出さない。いや、口を出さない、というのは正確ではない。GNU arch は 能動的に何かをしないだけではなく、受動的に何かを監視するようなこと すらしない。unix の言葉で言えば何かデーモンプロセスのようなものが 走っているわけではない。「ははー、こいつ、いまこんな修正してやがる。 じゃあ次のコミットに備えてこうしておこう」- その手の処理は一切しな い。GNU arch は君が何をしているか知らないのだ。

GNU arch が君の変更を知るのは二番目にあげた処理、つまりコミッ トするために次に tla commit が実行された時だ。このコマンドが呼び出 されると GNU arch は最後に tla commit あるいは tla import が呼び出 された時点でのツリーの様子と現時点での様子の違いを完全に把握するた めにプロジェクトツリー全体をスキャンする。君は言う。そんなことしたっ て無駄だ。だって直前のツリーなんてもうどこにも存在しちゃいない。い ま修正を加えたばかりだぞ、と。正論だ。実はtla はこの比較のために、 commit/import するたびに、その時点のツリー全体を丸ごとコピーして {arch}管理領域にもう1セット保存しておくのだ。このコピーのことをプ リスティンコピーと言う。まあ、世の中それなりにうまくできているのだ。

tla changes(1)

あまり話しを遠くまで進める前に、前のサンプルにちょっとイタズラして みよう。main.c を適当にいじって保存し、tla changes コマンドを叩い てみる:

$ tla changes
* looking for octopus@bluegate.org--2004/test--proj--1.0--base-0 to compare with
* comparing to octopus@bluegate.org--2004/test--proj--1.0--base-0
M  main.c
$ 

M という文字で始まる行によって、main.c に修正が入ったことが わかる。実際の修正内容を見たい場合には --diffs というオプションを つけると良い:

$ tla changes --diffs
* looking for octopus@bluegate.org--2004/test--proj--1.0--base-0 to compare with
* comparing to octopus@bluegate.org--2004/test--proj--1.0--base-0
M  main.c

* modified files

--- orig/main.c
+++ mod/main.c
@@ -1,5 +1,8 @@
 #include "./inc/tools.h"
 
+/*
+    main function:
+*/
 int main()
 {
         hello_world();

$ 

このように GNU diff 形式で表示してくれる。今回は 3 行コメン トを入れたことがわかる。どんな変更をしたか確認したいことはよくある。 たとえば昨日の晩徹夜で作業を続け、次の日の午後コンピュータの前でよ だれを垂らして気を失っている自分に気がついたとする。最後に何をした かなんてもちろん誰も覚えてはいない。そんなときにはこのコマン ドを使って変更点を調べよう。コミットする直前に、おそらく 90 % 以上 の確立で私はこのコマンドを叩く。一番よく利用されるコマンドかも知れ ない。

プロジェクトツリー内のファイルに対する修正についてもう少し詳 しく考えてみよう。修正にはファイルの内容の変更のほかにももう少しい ろいろな修正が考えられる。まずファイルのパーミッションを修正するよ うな場合。それから、既存のファイルを削除したり、新しいファイルを追 加したりするような場合だ。このうちファイルを新たに追加した場合には やっかいなことがおこる可能性がある。前章で少し説明したように、新し いファイルの名前が =tagging-method が適切に設定されていなければ今 回のコミットに伴うスキャンで GNU arch がそれをソースファイルと認識 できない可能性があるのだ。

またいたずらしてみよう。まず main.c の修正はそのままにしてお いて、cc.sh のパーミッションを変更してから tla changes を実行して みる:

$ ls -l
total 36
-rwxrwxr-x    1 octopus  octopus        40 May  5 11:54 cc.sh
-rwxrwxr-x    1 octopus  octopus     13667 May  5 12:07 hw
drwxrwxr-x    2 octopus  octopus      4096 May  5 11:53 inc
drwxrwxr-x    2 octopus  octopus      4096 May  5 11:53 lib
-rw-rw-r--    1 octopus  octopus       110 May  7 12:17 main.c
drwxrwxr-x    4 octopus  octopus      4096 May  5 19:04 {arch}
$ chmod -x cc.sh
$ ls -l cc.sh
-rw-rw-r--    1 octopus  octopus        40  5月  5 11:54 cc.sh
$ tla changes
* looking for octopus@bluegate.org--2004/test--proj--1.0--base-0 to compare with
* comparing to octopus@bluegate.org--2004/test--proj--1.0--base-0
-- cc.sh
M  main.c
$ 

-- cc.sh という行が増えている。-- はパーミッションに変化があっ たことを示す表示だ。やはり --diffs オプションをつけると詳しい状況 がわかる:

$ tla changes --diffs
* looking for octopus@bluegate.org--2004/test--proj--1.0--base-0 to compare with
* comparing to octopus@bluegate.org--2004/test--proj--1.0--base-0
-- cc.sh
M  main.c

* file metadata changed

    ./cc.sh
        --permissions 775
        => --permissions 664

* modified files

--- orig/main.c
+++ mod/main.c
@@ -1,5 +1,8 @@
 #include "./inc/tools.h"
 
+/*
+    main function:
+*/
 int main()
 {
         hello_world();

$ 

main.c の修正のほかに、--permissions のような行が表示され、 775 から 664 に変化したことを教えてくれている。このあたりの話はす べてプロジェクトツリー上でおきていることで、アーカイブ領域とは何の 関係もない。

undo と redo

さあ、イタズラはこのくらいにして、元に戻そう。main.c をエディ タでもう一度いじって、cc.sh に対しても chmod しなおせば良いのだが もっとスマートな方法がある。tla undo だ。このコマンドは修正する前 に、最後に実行した import/commit コマンド時点の状態までツリーを戻 してくれる:

$ tla undo
* linting the source tree
* reverting changes
M   main.c
--  cc.sh
$ ls
,,undo-1  cc.sh  hw  inc  lib  main.c  {arch}
$ ls -l cc.sh
-rwxrwxr-x    1 octopus  octopus        40  5月  7 13:19 cc.sh
$ 

main.c の内容を cat なり more なりで確認してほしい。cc.sh の パーミッションも元に戻っているのがわかるだろう。問題は ,,undo-1 と いう、奇妙なファイルがあることだ。このファイルの正体は、実はなんの 変哲もないただのディレクトリで、チェンジセットと呼ばれるデータが入っ ている。,, でディレクトリ名が始まるのは GNU arch がジャンクファイ ルに分類するためだ。この形のファイルはいつなんどき勝手に削除されて も文句は言えない。そういう決まりがある。ここにはついさっきやったツ リーに対するイタズラの詳細が記録されている。絵に書くとこんな感じだ:

図 3.5. base-0, base-0 への修正を加えたツリー、,,undo-1 の間の関 係

base-0, base-0 への修正を加えたツリー、,,undo-1 の間の関 係

どこかで見た図だとは思わないだろうか? そう、第一章で説明した GNU diff と GNU patch の絵に似ている。はっきり言ってそっくりだ。あ そこでは GNU diff/GNU patch が取り扱っていたのは一つのファイルだっ た。tla undo は GNU diff のツリーバージョンなのだ。ツリーとツリー の間の差分を計算して、それを ,,undo-1 に保存する。これが tla undo だ。とすると、それと反対のことをするコマンド、つまり GNU patch の ツリー版も存在しなくては理屈に合わない。まったくその通りで、tla redo というコマンドがある。これは tla undo の結果を取り消す、つま り、もう一度イタズラをした状態にツリーを戻すためのコマンドだ。やっ てみよう:

$ tla redo
* linting the source tree
M   main.c
--  cc.sh
$ ls
cc.sh  hw  inc	lib  main.c  {arch}
$ tla changes
* looking for octopus@bluegate.org--2004/test--proj--1.0--base-0 to compare with
* comparing to octopus@bluegate.org--2004/test--proj--1.0--base-0
-- cc.sh
M  main.c
$ 

tla changes の結果が、イタズラしたときと同じになっているだろ う。同時に ,,undo-1 というディレクトリが消えている。ツリーを元に戻 すために tla redo が利用したからだ。いろいろ説明してきたが、我々は まだアーカイブ領域には一切手をつけていない。tla undo も tla redo もプロジェクトツリーにのみ作用し、アーカイブには一切書き込みしない ことに注意してほしい。

修正のコミット

話を進めようと思う。今回のいたずらを実際の修正点と見なしてコ ミットしてみよう。コミットする一番簡単な方法は -L オプションの後に ログメッセージをつけて単に tla commit を呼び出すことだ:

$ tla commit -L'hoge'
* update pristine tree (octopus@bluegate.org--2004/test--proj--1.0--base-0 => test--proj--1.0--patch-1)
* commited octopus@bluegate.org--2004/test--proj--1.0--patch-1
$ 

base-0 の次のリビジョン、patch-1 ができた。'hoge' は、日本版 'foo' のことだ[13]。-L の後の文字列がロ グメッセージとして今回のリビジョン patch-1 に付随したメッセージと して保存される。アーカイブの状態を確認したい場合は例によって tla abrowse を実行する。オプションはたくさんあると言ったが、たとえば --desc オプションなどをつけると、かなりいろいろな情報をコンパクト に表示できる:

$ tla abrowse --desc
octopus@bluegate.org--2004
  test
    test--proj
      test--proj--1.0

        base-0    (initial import)
          Wed May  5 19:04:43 JST 2004      octopus <octopus@bluegate.org>
          initial import

        patch-1    (simple changeset)
          Fri May  7 14:01:34 JST 2004      octopus <octopus@bluegate.org>
          hoge

$ 

hoge の文字が表示されているのがわかると思う。tla abrowse は さまざまな引数をとり、いろいろな側面からアーカイブの内容を表示する 機能を持っている。いずれもアーカイブに対する参照だけなので、ぜひ試 してみてほしい。tla abrowse と同様の表示をする tla changelog とい うコマンドもある。似たようなコマンドが二つあるのは単に歴史的な理由 からだ。tla abrowse の方が後にできた新しいコマンドなので、こちらを 利用するのがおすすめだ。

ところで -L オプションではたいした量のログメッセージは書けな い。腰をすえてじっくりログメッセージを作りたい人は、まず tla make-log コマンドを使ってログファイルの元になるファイルを作る。見 るもおぞましいファイル名をもったログのテンプレートファイルがプロジェ クトツリーのルートに作成される。

$ tla make-log
/home/octopus/proj/++log.test--proj--1.0--octopus@bluegate.org--2004
$ ls
++log.test--proj--1.0--octopus@bluegate.org--2004  hw	lib	{arch}
cc.sh						   inc	main.c
$ 

tla make-log はプロジェクトツリー上での実際の修正を済ませ てこれからコミットするという直前に作っても良いし、修正前にあらかじ め作っておいても良い。more でこのファイルの中身をのぞいてみよう:

$ more ./++log.test--proj--1.0--octopus@bluegate.org--2004
Summary: 
Keywords: 

$ 

ファイルの中には Summary: とKeywords: の二つの文字列がある。 ログのタイトルとなる要約の文字列はSummary: の後に書く。Summary: の 後に最低一つは空白を置いてやるほうが良い。ログメッセージが長くなる 場合には、Keywords: の行の下に一行空行をいれて、その後にログの本文 を書いてやる。たとえばこんな具合だ(XXX:日本語の問題):

$ more ./++log.test--proj--1.0--octopus@bluegate.org--2004
Summary: add an empty file.
Keywords: 

add an empty file for the test of 'tla changes'.

$ 

このファイルの Summary: と Keyword: の文字そのものや、 Keyword: の後に一行空行を入れることに注意してほしい。このファイル は RFC822 準拠の形式をしているので、これに従わない場合にはエラーと なってしまう。もう一度コミットしてみよう。GNU arch では、コミット は少なくともツリーになんらかの変更がされない限り受け付けない。そこ で、今度はイタズラで空のファイルを追加してみる:

$ touch sub.c
$ ls
++log.test--proj--1.0--octopus@bluegate.org--2004  hw	lib	sub.c
cc.sh						   inc	main.c	{arch}
$ tla changes
* looking for octopus@bluegate.org--2004/test--proj--1.0--patch-1 to compare with
* comparing to octopus@bluegate.org--2004/test--proj--1.0--patch-1
A  sub.c
$ 

sub.c というファイルを追加した。touch コマンドは空のファイ ルを作るためのコマンドだ。その後 tla changes の出力を見てみる。'A' で始まる行は追加されたファイルを示している。'M' と 'A' が出てきた が 'D' というのもあってファイルが削除された場合にはこの表示が出る。 ではコミットしてみよう。ログファイルがあるので今回は -L は不要だ:

$ tla commit
A  sub.c
* update pristine tree (octopus@bluegate.org--2004/test--proj--1.0--patch-1 => test--proj--1.0--patch-2)
* commited octopus@bluegate.org--2004/test--proj--1.0--patch-2
$ 

リビジョン patch-2 ができて、嫌なログファイルも消えてくれ た。tla abrowse してみよう:

$ ls
cc.sh  hw  inc	lib  main.c  sub.c  {arch}
$ tla abrowse --desc
octopus@bluegate.org--2004
  test
    test--proj
      test--proj--1.0

        base-0    (initial import)
          Wed May  5 19:04:43 JST 2004      octopus <octopus@bluegate.org>
          initial import

        patch-1    (simple changeset)
          Fri May  7 14:01:34 JST 2004      octopus <octopus@bluegate.org>
          hoge

        patch-2    (simple changeset)
          Fri May  7 16:50:28 JST 2004      octopus <octopus@bluegate.org>
          add an empty file.

$ 

ちょっとくどいが、'D' の出力を見るために sub.c を削除して からもう一度だけコミットを練習してみよう。こんな感じだ:

$ rm sub.c
$ ls
cc.sh  hw  inc	lib  main.c  {arch}
$ tla changes
* looking for octopus@bluegate.org--2004/test--proj--1.0--patch-2 to compare with
* comparing to octopus@bluegate.org--2004/test--proj--1.0--patch-2
D  sub.c
$ tla commit -L'delete sub.c'
D  sub.c
* update pristine tree (octopus@bluegate.org--2004/test--proj--1.0--patch-2 => test--proj--1.0--patch-3)
* commited octopus@bluegate.org--2004/test--proj--1.0--patch-3
$ tla abrowse --desc
octopus@bluegate.org--2004
  test
    test--proj
      test--proj--1.0

        base-0    (initial import)
          Wed May  5 19:04:43 JST 2004      octopus <octopus@bluegate.org>
          initial import

        patch-1    (simple changeset)
          Fri May  7 14:01:34 JST 2004      octopus <octopus@bluegate.org>
          hoge

        patch-2    (simple changeset)
          Fri May  7 16:50:28 JST 2004      octopus <octopus@bluegate.org>
          add an empty file.

        patch-3    (simple changeset)
          Fri May  7 16:54:08 JST 2004      octopus <octopus@bluegate.org>
          delete sub.c

$ 

何か重要な変更をした後でも、コミットが済んだらひと安心だ。 君の修正はすべてアーカイブに保存されたことになるし、アーカイブは 追加される一方で、削除されることはないからだ。ディスクがクラッシュ せず、アーカイブ用のファイルシステムを GNU arch 以外のプログラム で直接いじらない限り、君の修正は永久に保存されたことになる。プロ ジェクトツリーは作業領域に過ぎないから、削除しても大丈夫だ。既に 紹介した tla get コマンドでいつでもプロジェクトツリーを復元する ことができる。ぜひためしてみてほしい。

プリスティン・コピー

一番よく利用されるのは、tla commit だ。これは作業中のプロジェ クトツリーの内容と、作業開始時点の内容、つまりアーカイブバージョン の中の最新リビジョンとの間の差分を計算する。GNU arch では差分の結 果は単なるパッチファイルではなく、チェンジセットというデータ構造と して求めるのだった。tla commit はこのチェンジセットをアーカイブの 該当バージョン用の領域に追加し、リビジョンを増やす。リビジョンには commit のオプションで特に指定しなければ、patch-10 のような形のリビ ジョンを作る。patch-10 には二つの意味がある。ひとつは前のリビジョ ンと作業コピーとの差分を元にして計算したチェンジセット、もう一つは その結果追加されたリビジョンのことだ。

ところで、ここでよく考えてみてもらいたいのだが、最後のリビジョ ンとプロジェクトツリーの間の差分を比較するためには、本来であればリ ビジョンにアクセスしなくてはならない。ひとたびできたリビジョンは永 続的なデータであり、それはアーカイブにある。後で説明するが、アーカ イブは別にプロジェクトツリーのあるマシンと同じマシンになければなら ないという制約はない。もしリモートアーカイブなら、ネットワークにつ ながっていなくてはアクセスできない。これは不便だ。君は桜の木の下で ラップトップを広げてひと仕事したかったのだ。

そこでプロジェクトツリーは自分が最後にアクセスした最新リビジョ ンのコピーを{arch}管理領域配下にデフォルトでは1世代だけキャッシュしてい る。これをプリスティン・コピーと言う。だから今話してきた差分の表示 はプロジェクトツリーにアクセスできさえすれば実行できるのだ。

tla changes --diffs の結果が気に入らない場合、最後のリビジョ ンにプロジェクトツリーの内容を戻すことができる。これは普通は今言っ たプリスティン・コピーをプロジェクトツリーの内容に上書きすることで 行う。いま話したのと同じ理由で、この操作もアーカイブにアクセスする ことなしに実行できる。これには tla undo コマンドを使う:

よくあるトラブル

ここでは日々の利用でよく遭遇する問題について説明する。良い質 問を補遺にある方法のどれかで私に送ってもらえれば、この節はより一般 的により豊富により洗練されたものとなっていくだろう。

プロジェクトツリー中に恐ろしい名前のファイルができた

GNU arch のコマンドの一部はアトミックな処理を必要としてい る。この実現のためにプロジェクトツリー中に一時ファイルを作成する ことがよくある。データベースに詳しい人ならご存知だとは思うが、こ ういうひとまとまりの処理をトランザクションと言う。トランザクショ ンが途中で中断されると、トランザクションでやるはずだったすべての 処理が取り消される。この場合トランザクションを構成するために必要 だった一時ファイルは取り残される。君の見ている恐ろしいファイルは おそらくこの一時ファイルだと考えられる。具体的には以下のような名 前のファイルだ(XXX:)

これらはいずれも安全に削除できる。慣れるまでは削除するのに 抵抗があると思うが、問題はない。万が一間違ったものを消してしまっ たとしても、所詮プロジェクトツリー内部の問題だ。どうしてもわから なくなったのなら tla get でフレッシュなプロジェクトツリーを再構 築するまでだ。

コミットに失敗する

コミットに失敗するとき、XX のようなエラーが出ることがある。 これは前回のコミットが異常終了するなどして、内部的なロックファイ ルが残ってしまった場合におこる。これには tla lock-revision の -b オプションを使ってロックを解除する。

ロックを解除してもアーカイブにあるデータや、プロジェクトツ リーの内容が壊れることはない。これは純粋に排他制御だけに関係した 問題だからだ。

tla changes コマンドの出力についての詳細な説明。パー ミッションが変わったときとかファイル名がかわったときとか。

外部インベントリタグを持ったファイルをファイルだけ 削除してしまった

この章のまとめ

この章は、ちょっと盛りだくさんだったかも知れないが、最初自分 が始めて GNU arch を使ったときにとまどったことなどをできるだけ思い 起こして一歩一歩書いてみた。(XXX) この中で一番重要なコマンドをあげ ろと言われたら、tla commit, tla changes, tla undo, tla redo, tla abrowse の5個だろうか。これだけ知っていれば、パンと水だけ与えられ た囚人程度には、なんとかやっていける。この中のコマンドでアーカイブ に対して書き込み処理をするのは tla commit だけであることに注意して ほしい。tla commit はアーカイブに対して書き込み処理を実行すること ができる GNU arch の数少ないコマンドの一つだ。



[4] V の部分は補遺にあるようにい くつかの数字をピリオドで区切ったものになる。

[5] このためにも、 アーカイブ名に適切な E-mail アドレスを設定することが重要になる。

[6] もちろんネットワークが切断されていたり、回線の早さ からくる制約はあるが、論理的な制約ではない。

[7] emacs エディタなら foo~ とか #foo.bar# のような雰 囲気でディレクトリに残ることが多い。

[8] CVS で言う、CVS ディレクトリにあたる。

[9] これは通常のエディタで編集可能なテ キストファイルである。

[10] 正直言って、このサ ンプルは明らかに改良が必要だと考えている。汎用的なデータを管理で きると言っておきながら結局プログラム言語を例としなくてはならない ことについては本当に申し訳ない気がする。もっと実践的でプログラム に依存しないような汎用的な例でこのサンプルは書き換える必要がある と感じている。

[11] 正確には現在では利用され ないが下位互換性を維持するための implicit という方法もあるがここ では扱わない。

[12] 特殊なリビジョン version-0 と versionfix-n という形のリビジョンを 作ることもできるが、これらの利用は推奨されていない。詳しくは補遺を 参照してほしい。

[13] しかし不思議なことに日本には'bar', 'baz' に当たるものはない。

第4章 インベントリ

前の章では一人で一つの開発ラインをバージョン管理するのに必要 な基本的なコマンドについて一通り見てきた。主に基本的なコマンドの紹 介をすることが目的であったため、ファイルの個数も、ごく少数の構成に とどめた。この章では、すでに別の方法で管理されているソースファイル を GNU arch 管理下に置いたり、たくさんのソースファイルから構成され る未管理のディレクトリをGNU arch管理下に置く方法について説明する。 基本的には前章の応用だが、たくさんのファイルを一度にインポートしよ うとすると、ファイルタイプ識別やインベントリ識別からくるエラーでう まくいかないことが多くなる。そこで前半では GNU arch 特有の概念 「インベントリ」について詳しく説明し、インベントリタグ とファイルのアイデンティティー、タグづけの方法などとの関係について 議論する。そして後半でこの応用として既存のプロジェクトを GNU arch 管理下に 2 通りの方法でインポートしてみる。この章を理解すれば、な ぜある場面であるファイルがソースファイルと認識されたり、そうならな かったりするのか、また、明示的なタグ付けの方法ではなぜファイル名称 の変更に注意しなくてはならないのか、また arch-tag: がなぜ必要なの かを明らかになるだろう。

=tagging-method

あるプロジェクトツリーをアーカイブバージョンの最初のリビジョ ンとしてインポートしたり、その後プロジェクトツリーに加えた変更点を 直前のリビジョンからの差分としてコミットしたりする時点で、GNU arch は常に前のリビジョンの内容と比較して、プロジェクトツリーに何が起き たかをスキャンする。プロジェクト中のあるファイルには変更が加えられ ているかも知れないし、新しいファイルが追加されたり既存のファイルが 削除されていたり、別のサブディレクトリに移動していたりすることもあ るだろう。GNU arch はプロジェクトツリー中のすべてのファイルを管理 対象にするわけではない。ある決まった規則にしたがっているファイルだ けをバージョン管理対象ファイルとみなす。あるファイルがGNU arch の 管理対象であるかどうかは、3種類のテストによって決められる。最初に ファイル名称がどんな形をしているかのチェック、二番目に、ファイルに 正しく「インベントリ」が振られているかのチェックだ。「インベントリ」 と「非認識」という言葉が説明なしに出てきたが、これについても順を追っ て説明していく。

二つのチェックは設定によってかなり自由に変更することができる。 設定は、主にプロジェクトツリーの{arch} 管理領域にある =tagging-method という定義ファイルの内容によって決まるが、それ以外 の情報も関係してくる。=tagging-method ファイルは tla init-tree コ マンドを発行してあるツリーを最初にプロジェクトツリーにした時点で、 このファイルの内容はデフォルト値に初期化される。

第一のチェック - ファイルタイプチェック

最初は、ファイルタイプのチェックだ。GNU arch はファイルを 以下の 6 種類に分類する決まりがある。プロジェクトツリー中のどの ファイルも、必ず以下の 6 種類のどれかに分類されます。このような 複雑な分類には、それぞれきちんとした意味があると考える人もいるが、 少なくとも最初のうちはあまり深く掘り下げず、そのようなものだと考 えると良いと思う。必ず覚える必要はないものだが、覚えようと思う人 は不規則動詞の変化を覚える方の脳みそで覚えよう。いろいろな名前が ついているが、言葉の意味を深追いせず、単にグループ1, グループ2 ... グループ 6 の別名だと考えても良いかも知れない。グループ 4 の ソースファイルが、主なバージョン管理対象となる。

ジャンクファイル

ゴミファイル、 たとえば作業用に一時的に使う中間ファイルなどを分類することを 狙っている。主にディレクトリごとにある .arch-inventory ファ イル、または=tagging-method ファイルの、junk 正規表現で設定 するが、',,' で始まるファイルは常にジャンクと見なされる。

バックアップファイル

管理対象で はないが、GNU arch が注意して扱う必要のあるファイル。エディ タの作るバックアップファイルなどを分類することを狙っている。 ディレクトリごとにある.arch-inventory ファイル、または =tagging-method ファイルの、backup 正規表現で設定する。

プレシャスファイル

管理対象では ないが、GNU arch が注意して扱う必要のあるファイル。バックアッ プファイルとは少し違った扱いをするため、別のグループとして定 義されている。主に ディレクトリごとにある .arch-inventory ファ イル、または=tagging-method ファイルの、precious 正規表現で 設定するが、'++' で始まるファイルは常にプレシャスと見なされ る。precious は「貴重な」という意味。

ソースファイル

管理対象となるファ イル。常にバージョン管理対象ファイルと見なされる。ディレクト リごとにある .arch-inventory ファイル、または=tagging-method ファイルの source 正規表現で設定する。

除外ファイル

管理対象に含めない ことを明示的に指定するために設定する。GNU arch はデフォルト では import や commit 時に非認識ファイルが一つでもツリー中に 存在するとエラーとする。このようなファイルを明示的に除外ファ イルに加えることでエラーを回避することができる。除外ファイル はディレクトリごとにある .arch-inventory ファイル、または =tagging-method ファイルの exclude 正規表現で設定する。

非認識ファイル

上記のどれにも当 てはまらないファイルは、非認識ファイルとして「認識」される。 非認識ファイルが存在する場合には、原則として GNU arch は import や commit でエラーを発する。あるパターンに合うファイ ルを明示的に非認識ファイルとして「認識」させるには、ディレク トリごとの .arch-inventory ファイル、または =tagging-method ファイルの unrecognized 正規表現で設定することもできる。

プレシャスはどのような意味で削除されないのか。junk はど のようなタイミングで削除されるのか、などなど。

どのファイルがどのグループに属するかは主に =tagging-method ファイルで行なう。ディレクトリごとに .arch-inventory ファイ ルを設定することもできるが、話が煩雑になるので GNU arch に慣れ るまではあまり使わないほうが良い。

第二のチェック - インベントリチェック

インベントリチェックは、第一のチェックでソースファイルに分 類されたファイルが、正しいインベントリidを持っているかどうかを調 べる。インベントリidについてはあらためて説明するが、ここでは、ソー スファイルを区別するための「キー」だと考えてほしい。GNU arch で は、ファイル名の違いによってファイル同士を区別する場合のほかに、 この「キー」の一致不一致によって二つのファイルの起源が同一のもの かどうかを判断する場面があるので、ソースファイルはかならずインベ ントリid を持たなくてはならない。

インベントリid はインベントリidを計算するための元になる情 報を、あらかじめ保持しているさまざまな情報から計算する。保持情報 は大きく三つの場所に分類される。

  • ファイル名そのもの

  • ファイルの内部

  • ファイルの外部

ファイルの内部の保持情報は、特殊な文字列をファイルの先頭ま たは末尾のほうに埋め込むことで表す。具体的には arch-tag: という 文字列を書き、その後に文字列を続けることで表す。この文字列のこと を arch タグと呼ぶ。arch タグの行は、本来そのファイルが表現しよ うとする内容とは無関係だ。たとえばこのファイルが C 言語のソース コードであったとしても、そのソースコードでやろうとしている目的と は何の関係もない。arch タグはファイルの中にありながら、そのファ イル自身に関係した付加情報を表現する。このような情報のことを「メ タ情報」と呼んだりすることもある。arch タグを埋め込むファイルが プログラムのソースコードのようなものである場合、arch-tag: の行が 問題を起こさないように、それぞれの言語のコメントの中に書く必要が ある。たとえば C 言語なら:

/*
    arch-tag: Tez Kamihira Fri Apr 16 16:15:11 JST 2004 (foo.c)
*/

シェルスクリプト、Perl, Python のような言語なら:

#    arch-tag: Tez Kamihira Fri Apr 16 16:15:11 JST 2004 (foo.c)

Pascal なら:

{
     arch-tag: Tez Kamihira Fri Apr 16 16:15:11 JST 2004 (foo.c)
}

htmlやXML なら:

<!--
     arch-tag: Tez Kamihira Fri Apr 16 16:15:11 JST 2004 (foo.c)
-->

のようになる。言語ごとの arch-tag: のサンプルについて は補遺にまとめた。

arch-tag: に利用する文字列はまったくの任意だが、すでにプロ ジェクトツリー中に存在している別のファイルのタグと重複してはいけ ない。これに違反すると import や commit 時に GNU arch はエラーを 出す。プロジェクトに新しくファイルを追加するときに、既存のファイ ルをもとにしようとコピーしたような場合によくおこる。この場合には 新しいファイルの arch-tag: の部分だけを重複しないような文字列に 変更してやるだけでエラーは表示されなくなる。

重複しないような文字列をいちいち考えずに作り出す方法がある と便利だ。GNU arch コミュニティーのメンバーは、おおきく二つの流 儀でこれをやることが多いようだ。一つはいまいくつかの例で示したよ うな、名前、現在の時刻をしめす文字列、それからこのファイルの現時 点での名前、これらを組み合わせた文字列だ。もう一つは UUID と呼ば れる文字列を利用する方法だ。UUIDについては補遺に詳しく書いた。C 言語で UUID を使ってタグを振ると、たとえば以下のようになるだろう:

/*
    arch-tag: 9d3a97ec-dc74-445f-bcf0-234ebb054702
*/

ファイルの外部の保持情報は、ファイルのあるディレクトリの、. arch-ids という名前のディレクトリに保存される。ところで GNU arch では、ディレクトリにもインベントリidをつけることができる。ディレ クトリは通常のファイルと違って、内部タグを使うことができないので、 必然的に外部タグを使って表現することになる。ディレクトリの外部タ グ情報は、やはりそのディレクトリの .arch-ids ディレクトリに保存 される。

外部タグの設定は tla add-id コマンドと、tla explicit-default コマンドで行う。tla add-id コマンドはファイルご との個別の外部タグを設定するのに利用され、tla explicit-defaultコ マンドはあるディレクトリにあるファイル全体に対する既定値に関係し た情報を設定する。tla add-id で振られる個別の外部タグは、対象と なるファイルの名前を foo としたとき、.arch-ids/foo.id というファ イルに保存される。たとえば hello.c というファイルには .arch-ids/hello.c.id が、index.html というファイルには . arch-ids/index.html.id がそれぞれ保存領域になる。ファイルの中に は、実際のインベントリid の元になる文字列がある。すでに説明した とおり、インベントリidは他と区別がつく文字列であれば十分なので、 tla add-id コマンドで特に明示的な指定をしない限り、GNU arch が自 動的に重複しないような文字列を設定してくれる。具体的にはさきほど 説明した第一の方式に近い文字列が生成されるのだが、ほとんどのユー ザにとってはその具体的な形にはあまり興味がないだろう。tla add-id コマンドはまた、ディレクトリ用の外部タグ情報を作ることもできる。 これは、ディレクトリを d とすれば、つねに d/.arch-ids/=id という 名前のファイルに保存するという決まりがある。これはファイルと同じ ように d/.arch-ids/d.id という名前にしてしまうと、このディレクト リ中にある通常ファイル d のタグと区別がつかなくなってしまうから だ。

あるディレクトリにあるファイルすべてに外部タグを設定せずに 既定値を一つだけ設定できると便利だ。これには tla explicit-default コマンドを使う。デフォルト値には、強いデフォル ト値と呼ばれるものと、弱いデフォルト値と呼ばれるふたつの値がある。 tla explicit-default コマンドはこの両方を個別に設定することがで きる。強いデフォルト値は、このディレクトリにあるファイルすべてに 対して適用される。弱いデフォルト値は、このディレクトリにあるファ イルで、内部タグを持たないものに対してのみ適用される。

では、内部タグと外部タグのどちらがどのような場面で利用され るのだろうか? 以下ではこの判断の詳細について述べる。

一つのファイルに関係した複数の保持情報が存在することがある ので、インベントリidを決めるには、この中のどの情報を使うべきか、 また利用できる複数の情報があるとき、どの情報を他に優先して利用す べきかを決めなくてはならない。この優先規則のことをタグづけの方法 と言う。タグづけの方法には以下の三種類がある。

  • explicit

  • tagline

  • names

警告

GNU arch システムでは「タグ」という言葉がまったく違った 二つの意味で利用される。一つはここで取り扱っているインベントリ idを決めるタグづけの方法。もう一つは GNU arch のバージョンを分 岐させるときに利用する tla tag コマンドだ。両者を区別して混乱 しないようにしてほしい。

タグづけの方法は、tla id-tagging-method コマンドによって設 定することができる。tla 1.2 ではデフォルトでは explicit の方法を 利用するようになっているので、他の二つの方法を利用する場合にはこ のコマンドで変更してやる必要がある。タグづけの方法は初期インポー ト後でも自由に変えることができるし、変更によって管理対象ファイル を失うことはないが、てを触れていないファイルが削除され、また追加 されたような記録が残ることもあるので初期インポート時までに適切な 形に設定することを推奨する。

チェックの詳細

前節での、インベントリに関するさまざまな概念を用いてファイル 分類のアルゴリズムの詳細を以下に述べる。繰り返しになるが、この節で の議論は、ファイル分類規則からくるトラブルにより import やcommit がうまく行かないような状況にないのであればぜひとも必要な知識という わけではない。私自身、今回このような形の文章を書くのでなければその 詳細を知ることはなかったと思う。

まず第一のチェックをする。ファイル名の形だけから、ファイルを 六つのどれかのタイプに分類する。分類の規則はファイルのあるディレク トリに .arch-inventory ファイルがあればその内容を、なければ {arch}/=tagging-method ファイルの内容を利用する。ただし ',,' で始 まるは常にジャンクファイルとみなし、'++' で始まるファイルは常にプ レシャスファイルであるとみなす。非認識ファイルがひとつでもあれば、 その時点でエラーになる。

第一のチェックでソースファイルにマッチしたものについて、第二 のインベントリチェックをする。(XXX)。

...

tla inventory

プロジェクトツリー中のファイルがどのタイプに分類されるかを確 認するには tla inventory コマンドを使う。このコマンドは非常にたく さんの引数をとる

tla inventory の出力は、二つ以上のグループを表示させるように 指示した場合、S,P,B,J,T,U のいずれかの文字の後にオプションで '?' 文字がくる。'?' が表示された場合、名前のマッチング規則だけを考えた 場合にはソースに分類されたが、それ以外の理由で別のグループに分類さ れたことを示している。具体的には現在のIDタグづけの方法では認識しな い形式のインベントリidであったり、そもそもインベントリid が振られ ていないような場合である。文字の意味はそれぞれ、ソースファイル、プ レシャスファイル、バックアップファイル、ジャンクファイル、ツリー、 アンレコグナイズ(非認識)の意味である。その後に空白が一文字くる。-- kind オプションを指定した場合には、次に 'd', '>', 'r' のいずれ かが来る。それぞれディレクトリ、シンボリックリンク、通常ファイル、 の区別を表現している。最後にファイル名のプロジェクトツリーからの相 対パス名が表示される。--ids オプションが指定された場合にはこの後に インベントリid が表示される。インベントリid を持たないファイルの場 合は ??? が表示される。

--f オプションはディレクトリ以外のファイルについてのみ表示し、 ディレクトリは含まない。これがデフォルトである。--d を指定すると逆 にディレクトリのみを表示し、それ以外のファイルは表示しない。-b は 両方を表示する。この三つは高々一つしか指定できない。

--all オプションは {arch}管理領域の配下についても表示するが、 あまり利用されることはない。--explicit ... は、 {arch}/=tagging-method ファイルの内容によらず、指定のIDタグづけの 方法によってチェックを行うことを意味する。

--untagged オプションはタグづけされていないファイルも表示に 含める(多分これは触れないほうがいい。意味としては、ファイルパター ンはソースだが、それ以外の理由でアンレコグナイズとみなされたファイ ルを表示するというもの。しかし、untagged-source ディレクティブが =tagging-method に追加された今では、意味があいまいになりつつあるの では???XXX:)。

ファイルがディレクトリでかつ、その中に {arch} という名前のサ ブディレクトリがある場合、このディレクトリは別の独立した GNU arch 管理領域とみなされる。この場合そのディレクトリはツリー属性であると みなされ(複数グループ表示時には) T で表示される。T の配下は別の GNU arch 管理領域だが、T 自身は現在のプロジェクトツリーの一部であ ることに注意すること。tla inventory は T と認識したディレクトリの 内部は走査対象から除外する。

通常のファイルはファイル内部に arch-tag によってインベントリ タグを埋め込むことができるが、明らかにディレクトリに対してはこの手 法を使うことができない。このためディレクトリは外部タグをつけるか、 タグをつけないかのいずれかを選ぶしかない。通常ディレクトリには外部 タグを振らないことが多い。

--ids で表示されるインベントリid の意味の列挙。. /libarch/inv-ids.cの、file_id() の調査。

先頭が ? はファイル名によるタグづけであることを示している。 E_は .arch-ids 配下のファイル, D_ は .arch-ids ディレクトリ自身の インベントリidをそれぞれ示す。 A_ は {arch}管理下のファイル、明示 的なタグがある場合 x_ 、.arch-ids/=all によるデフォルトタグの場合 a_, 内部インベントリタグによる場合 i_, 内部インベントリタグが存在 しない場合に限って利用される弱いデフォルトタグの場合 w_, k_ (XXXよ くわからない)、?_ (XXX)。意味はわからないが、シンボルの一覧は以上 でおわりと考えられる。

tla tree-lint

tla tree-lint は本質的には tla inventory コマンドと同じロジッ クを使ってプロジェクトツリーを走査するがエラーメッセージがより詳細 化されている。以下のようなエラーメッセージがある。

These files would be source but lack inventory ids (`tla add' or a tagline perhaps?):

「これらのファイルはソースファイルかも知れないが、インベント リid がついていない('tla add' あるいはtagline を使うと良いの では?)

説明

These files violate naming conventions:

これらのファイルは名前規約に違反している

説明

These symlinks point to nonexistent files:

これらのシンボリックリンクは存在しないファイル を指している

説明

These apparent source files lack inventory ids:

明らかにソースファイルだが、インベントリid が ついていない

説明

These explicit ids have no corresponding file:

明示的なid に対応するファイルが存在しない

説明

Duplicated ids among each group of files listed here:

それぞれのファイルグループ中に重複したイン ベントリidを持つものがある

説明

既存プロジェクトの移行

この節では既に存在している比較的規模の大きなソースコードを新 たに GNU arch で管理し始める方法について検討する。GNU arch の実践 的な利用においては ID タグづけの方法として explicit または tagline のどちらかを選択するのが現実的だが、この場合インベントリの問題が顕 著に現れてくるため、そのままの形ではうまくインポートできないことが 多い。この節ではインポートまでの手順について説明する。前節の内容を 基本として理解できていれば一見奇妙に見えるエラーの内容も整理して理 解することができるはずだ。初期インポートさえ済んでしまえば、あとは 普通のアーカイブバージョンとなんら変わることはなくなる。第 3 章で 説明した操作や、5章で説明するすべての操作が可能となる。

なお既存プロジェクトがすでに他のバージョン管理システムで管理 されており、最新のソースだけではなくそのプロジェクトの履歴も含めて 移行するケースについてはここでは扱わない。移行元が CVS の場合につ いてはサードパーティー製のツールがある。詳しくは補遺を見てほしい。

explicit による方法

tagline による方法

この章のまとめ

この章では、プロジェクトツリー中の各ファイルを、GNU arch が それぞれどのような種類のファイルとして認識するかについて説明した。 ファイルには 6 っつの種類があり、プロジェクトツリー中のすべてのファ イルはこのどれかに分類され、この中のソースファイルのみがバージョン 管理の対象となった。ソースファイルはファイル名のマッチング規則の他 に、正しいインベントリid を持っている必要があった。ファイルのマッ チング規則とインベントリidの決定方法は主に=tagging-method ファイル によって決まった。非認識のファイルがひとつでもプロジェクトツリーに 残っていると import や commit 処理は失敗し、これが初期インポートの エラーの原因として考えられる大きな要因の一つであることを説明た。

次の章では、既存のバージョンの分岐を、自分のマシン上に作成す る方法と、分岐後で親のバージョンとの間とのデータ交換に必要なコマン ドについての説明をする。逆説的な話ですが、既存のバージョンからの分 岐は、新規のバージョンでのインポートに関するトラブルが一切ない。分 岐元のバージョンがすでにプロジェクトツリーを正しい状態に設定してい るためだ。

インベントリid のタイプの説明。先頭に E_ とか ?_ とか付く 話と、その分類。tla inventory のオプションごとの詳細な説明。

第5章 ブランチとマージ

さて、この章から先が GNU arch の本当の凄さが発揮されることに なる。ようやく私も一番話たいことについて語れる。ほとんど涙目になっ ている私の姿を想像してほしい。前章までの議論は CVS のような従来の システムでも本質的に同じこどかできる。ひとり、もっと正確には一つの リポジトリで作業している時には GNU arch の本当の性質は表には出ない。 それは単なる「また別の」バージョン管理システムでしかないのだ。そこ までの機能しか必要がないのであれば、GNU arch をわざわざ理解する必 要はあまりないと思う。なんで同じようなことを二つも三つも憶えなくて はならないのだろうと思うかも知れない。しかし、ネットワーク越しに、 別のリポジトリとの間でのやりとりが絡んでくると状況は一変する。

この章では、ネットワーク上の他のアーカイブバージョンの内容か ら分岐処理によって別のマシン上のアーカイブバージョンを作る方法と、 この逆に自分のローカルマシン上のアーカイブを他のマシンから分岐でき る形に公開する方法について示そうと思う。その後、リモートアーカイブ 間でのデータの同期方法について議論する。データの同期はマージと呼ば れるが、マージのために用意された GNU arch のコマンドのいくつかを紹 介する。マージに関する問題はモダンなバージョン管理システムすべてが 現時点で抱えているもっともホットなトピックの一つだ。GNU arch もま だこの問題を完全には解いていないが、かなり良い振舞をするいくつかの マージコマンドを持っている。おそらく今現在この世に存在しているまと もなバージョン管理システムの中では、最も良い結果をもたらすものの一 つだと言えるだろう。それでも時にはぶさまなことになる。マージの問題 をきれいに解くのは非常に難しい。人類でこの問題をきれいにといたもの はまだいない。もし君がこの問題を完全に解いたら、間違いなくチューリ ング賞がもらえる。万が一もらえないようなら、私が受賞会場に乱入して メガホン片手に君の名前を書いた垂れ幕を振りかざして暴れよう。約束す る。

この章を理解すれば、君は基本的に GNU arch について一定の理解 をしているということができるのではないかと思う。GNU arch コミュニ ティーには自分のアーカイブを公開している人がたくさんいるので、それ らのどれかを使って、この章での結果を是非自分で確認してみてほしい。 アーカイブサーバになるのには少し知識がいるが、人のアーカイブの分岐 を自分のマシン上に作るのは非常に簡単な作業で済むし、間違った操作に よって親のアーカイブを壊してしまうようなことは一切ないので安心して 試してみてほしい。

ブランチ(分岐)

いつものように君はインターネット上にある面白そうなソフトウェ アを検索しているとする。で、お目当てのものが見つかった。それはフリー ソフトウェアで自由に使ってよいことがわかった。実際にいじってみるが 実に申し分のない動作をする。すばらしい。ただ、すばらしい機能拡張を 思い付いた。どうしてもこの機能を実装してみたい。作者にメールして、 いきなり一緒に開発してくれないかと切り出すのもおかしな話だ。なにせ この人とは会ったこともない。これからだって会う機会があるとは思えな い。なにせ彼はアルゼンチンに住んでいるのだ。これじゃ地球の裏側では ないか。

こんな状況で、彼がもし自分のプログラムを GNU arch の公開アー カイブ上のバージョンとして管理していたとすれば、君は実に運がいい。 彼になんのことわりもなく、一切彼のてをわずらわせることはなく、君の コンピュータ上に彼のプログラムのコピーを作ることができる。それもた だのコピーじゃない。このコピーは自分の由来を理解している。自分のご 先祖様が誰であったかを記憶しているのだ。いまどきそんな話、人間でも あまり聞かなくなった。今後、彼が彼のアーカイブバージョンに加えた修 正点を追加で君のアーカイブに取り込みながら、君は君で自分の機能拡張 作業を続けることができるのだ。このような用途のために君が自分のアー カイブ上に作ったバージョンを、彼のバージョンの「分岐」あるいは「ブ ランチ」と言う。君のブランチは、彼のバージョンととても良く似ている。 でもほんのちょっとだけ違っている。君は拡張モジュールを作っているか らだ。君のアイディアは良いものかも知れないし、そうでもないかも知れ ない。こういうことは普通、少しコーディングを続けてみないとはっきり しないことが多い。本質的に試行錯誤的な作業になることがおおい。一ヵ 月夢中でハックしてみて、やっぱりうまくいかなかったとあきらめること になるかも知れない。でもそれが何だろう? 別に彼に何かを頼んだわけで はない。黙って君がギブアップすれば良いだけのはなしだ。逆にアイディ アが身を結び、君の機能はとても汎用的で、彼自身にも、そしてそのソフ トウェアを使っている誰にとっても有益なものだと確信したとする。そん な時には彼にメールして、自分のアーカイブ位置を伝え、ちょっと面白い ものを作ったから、よければ取り込んでもらえないだろうかと頼む。彼が 気に入れば、これを取り込むことができる。これをマージと言う。マージ は彼の意志だけでやることができる行為だ。君には関係がない。君がする ことは自分のアーカイブをインターネット上に公開するだけだ。彼に対し て特殊な設定をする必要は何もない。

CVS のような集中型システムではこうはいかない。分岐は、親のリ ポジトリと同じリポジトリ内にしか作ることができないからだ。もし今問 題になっているプログラムが彼のマシン上の CVS で管理されていたとし よう。分岐を作ることができるのは君のマシンではなく、彼のマシンだ。 ということは、まずは君は彼のマシンに対するアクセス権限を得る必要が ある。これは君の仕事ではない。彼の仕事だ。しかしこれは実におかしな 話だ。これからハックしようとするのは君だ。彼じゃない。なのにそのこ とで彼に作業が発生するのだ。これはおかしい。考えてもみてほしい。一 度も会ったことのない男からある日突然メールが来て、あなたのプログラ ムの分岐を作りたいから、あなたのマシン上にアクセス権限をくれと言う。 そんな人間においそれとアクセスを許すことができるだろうか?

百歩譲って、アクセス権限をくれたとしよう。くれた方はどんな気 持だろうか。これだけのことを自分にしてくれたのだから、ぜひとも何ら かの成果を出さなくてはならない。もちろんそんな義務はないのだが、あ る日突然気が変わってギブアップというわけにはいかない。理由を彼に説 明して、自分はこれこれこういう理由で拡張できると思って始めたけれど、 うまくいかなかった、残念だ、という話をしなくてはならない。しなくて はならないわけじゃないが、良識のある人間ならそうするだろう。こんな ことをしなくてはならないと思うと、じつに憂鬱だ。どうなるか分からな いことを勝手に始めるのに、誰だって他人を巻き込みたくなんかないだろ う。で、結局良いアイディアがひらめいても、そこまでして分岐を作る気 にはならないだろう。これは重大な機会の損失だ。可能性は小さいかも知 れないがもし成功していたとすれば、君だけじゃない、そのソフトウェア を利用しているすべての人にとっての損失だ。君は私が何か多げさなこと を言っていると思うだろうか? 私はそうは思わない。

GNU arch ならこんな心配は何もしなくていい。君は勝手に始めら れる。そして勝手に辞められる。うまくいけば彼に伝える自由がある。も ちろんそうしない自由もある。彼は彼で君の申し出を受け入れる自由も拒 否する自由もある。誰も困らない。みんなトクをする。実際この仕組みで 損をする人がいるとしたらいったいそれは誰だろう。私に教えてほしい。

GNU arch で人のアーカイブバージョンの分岐を作るには特殊な設 定は何も要らない。まず、彼のアーカイブを登録する:

$ tla register-archive tez@kamihira.com--2004s \
      http://arch.bluegate.org/{archives}/tez@kamihira.com--2004s
$

分岐元のアーカイブバージョンを tez@kamihira.com--2004s/hello--world--1.0 とし、分岐先のバージョン を octopus@bluegate.org--2004/hello--world--1.1 として説明すると、まず 分岐先アーカイブバージョンを作成する:

$ tla archive-setup hello--world--1.1
…
$

注意

分岐元のバージョン名と分岐先のバージョン名の間にはなん の制約もない。ふたつのバージョンが別のアーカイブに存在してい る場合であれば、まったく同一の名前にすることすら可能だ。今の場合 であれば、tez@kamihira.com--2004s/hello--world--1.0 を foo@bleugate.org--2004/hello--world--1.0 なるバージョンに分岐する こともできる。また、octopus@bluegate.org--2004/non--sense--0.1 のよ うな名前に分岐することもできる。あとから混乱しないように自由にバー ジョン名を選択してほしい。

そして tla tag コマンドで実際に分岐バージョンを作る:

$ tla tag tez@kamihira.com--2004s/hello--world--1.0 \
          octopus@bluegate.org--2004/hello--world--1.1
…
$

注意

tla tag コマンドを実行すると、XXX のような警告が出るこ とがある。これは分岐元のアーカイブがサインつきアーカイブであること に関係している。詳しくはXXXのサインつきアーカイブを読んでほしい。

これで終りだ。本当にこれで全部なのだ。嘘じゃない。私を信じて ほしい。あとは君の hello--world--1.1 のプロジェクトツリー上で思う 存分ハックするだけだ。君がハックしている最中に、彼は彼で自分のリビ ジョンを進めることができる。こうして少しずつ君と彼のアーカイブバー ジョンはずれていく。彼とのずれをなくして同期させるには、君は彼の追 加修正分を時分のアーカイブバージョンに取り込まなくてはならない。こ れがマージだが、3節で詳しく説明する。分岐元のバージョンと、分岐先 のバージョンは明示的にマージコマンドを発行するまで独立に修正を加え ることができる。この間両者にはデータの授受は一切発生しない。たとえ ばGNU arch がバックグラウンドでお互いのバージョンから作ったプロジェ クトツリーに加えた変更点をリアルタイムに検出して、もう一方の関連し たリモートアーカイブバージョンに情報を転送したりすることはない。 GNU arch が実際データを交換するのは、XXX のマージコマンドのどれか を実行したときだけだ。だからどちらかのマシンがラップトップパソコン で、分岐後、マシンをネットワークから外して、喫茶店で作業を続けても もちろんなんの問題も発生しない。マージしたくなったときにネットワー クにつながっているだけで十分なのだ。

アーカイブの公開

1節では人のアーカイブバージョンの分岐を自分のマシンに作る方 法を説明した。この便利さを本当に実感できたら、君だって他の人にこの 便利さを味わってほしいと思うだろう。これがアーカイブの公開と呼ばれ るものだ。こっちは少し設定が必要になる。公開用の通信方式はいくつか 選択することができて、現時点で GNU arch がサポートしている主な方式 は WebDAV と呼ばれる Apache のような httpd サーバを使う方法と、 sftp と呼ばれる sshd サーバを使う方法があり、それぞれ設定方法は違っ てくる。ここではこの 2 種類の設定方法について説明する。

<IfModule mod_dav.c>
DavLockDB /tmp/dav.lock

Alias /arch /home/foo/arch

<Location /arch/>
Dav On
</Location>
</IfModule>

もう一つの方法は sftp というプロトコルを利用することである。 sftp は WebDAVほど有名ではないが、実は ssh プロトコル上に実装され たものであるので、ssh がインストールされているシステムであれば通常 は特別な設定なしに常に利用することができる。WebDAV が自分のアーカ イブを広く不特定多数の人々に公開するのに対して、sftp は自分だけが 利用するインターネットにそれぞれ接続された複数のあるような状況で、 どのマシンからもそのアーカイブを参照できるようにしたいという意味あ いが強い。sftp は ssh 上で動作するので、ネットワーク上のデータは暗 号化されて流れるためだ。もちろん WebDAV を利用しても https を利用 すれば同じなのだが、http/https プロトコルは非常に一般的に利用され ているので攻撃の対象となりやすい。また設定の仕方を誤ることで https に限定した設定を http の設定と混同したりする可能性も高い。人が大勢 集まる野球場のすぐ横に国家の諜報活動機関用の建物を建てるようなもの だ。(XXX:)。sftp は ftp と名前が良く似ているが、ソフトウェア構成上 は何の関係もない。繰り返すが sftp は ssh パッケージの一部と考える ことができるので、あらかじめセキュリティーを確保することが容易なの だ。

sftp には、サーバ側での設定は何もいらない。単に sshd が起動 されていて、そのマシンがインターネットに接続されており、ssh と同じ 設定にしたがったパスワードまたは公開鍵を手にしていさえすれば、その まま利用できる。クライアント側では以下のように register-archive す るだけだ:

$ tla register-archive octopus@bluegate.org--2004 \
      sftp://arch.bluegate.org/home/foo/{archives}/octopus@bluegate.org--2004
$

tla abrowse で接続テストをしてみよう:

$ tla abrowse -A octopus@bluegate.org--2004
…
$

ssh の設定によって、パスワードなどを聞かれることがある。これ に正しく答えるか、公開鍵を使って自動的に接続できるように設定すれば よい。このあたりの設定は ssh の設定そのものであるので、詳しくは ssh のマニュアルなどを参考にしてほしい。

マージの技法

マージに関係したコマンドは大きく三つの種類にわけて考えること ができる。一つは実際のマージについての各種の情報を確認するコマンド、 もう一つは実際にマージを実行するためのコマンド、最後にマージに関す る記録を保持するパッチログと呼ばれるデータを管理するためのコマンド、 この三つだ。普通は第1と第3グループのコマンドの一部を実行して、もし マージしたとしたらどのような結果になるかをチェックし、その後実際の マージコマンドを発行する形になる。チェックコマンドはプロジェクトツ リーに対して書き込み処理はしないので気軽に実行できる。一方マージコ マンドもプロジェクトツリーには書き込みが発生するが、アーカイブには 手を触れないので、マージ後にプロジェクトツリーがどのように変形した かを確認することができる。確認の結果プロジェクトツリーが意図した形 に変形していれば、コミットすることになる。これで始めてリビジョンが 追加され、修正点がアーカイブに永続的に保存される。

プロジェクトツリーに実際に書き込むコマンドも二種類に分類でき る。ひとつは過去にマージされたチェンジセットがどれであるかを記録し たパッチログという情報を書き換えるもの、もう一つは実際のソースファ イルを変形させるものである。パッチログは重複したマージを回避するた めに GNU arch が利用する重要な情報だ。パッチログの情報を調整すると、 すでに一度適用したチェンジセットを適用しなかったことにしたり、逆に 適用したことのないチェンジセットを適用したとみなしたりすることがで きる。通常はこのような操作は不要だが、特殊な場面では役にたつ。XXX のコマンドリファレンスにはすべての GNU arch のコマンドに対してデー タの書き込みが発生するかどうか、発生するとすればどの領域に対してか を示した。これを見てこの章のコマンドをいろいろと試してみてほしい。

マージコマンドは用途や場面に応じてみっつある。

tla replay

このコマンドは三つのマージコマンドのうちでもっとも単純なも のだ。replay に対する引数の与え方には三つの方法がある。まず、リ ビジョン名を指定すると、そのリビジョン名に対応するチェンジセット をプロジェクトツリーに対して適用する。これは成功するかも知れない し、衝突を起こして失敗するかも知れないが、いずれにせよ適用する。 リビジョン名に対応するチェンジセットが存在しない場合にはエラーを 返す。これは例えば継続によって作られたのではないベースリビジョン、 base-0 のようなものがそうだ。このコマンドは実際の適用前にパッチ ログを調べてすでにこのツリーに今回のチェンジセットが適用されてい ないかどうかを調べ、重複した適用を避けようとする。

引数にバージョン名を与えた場合は、そのバージョンに含まれる すべてのリビジョン名に対応するチェンジセットを適用する。適用はリ ビジョン番号が小さいものから順におこなわれ、やはりパッチログを チェックしてすでに適用されているものはスキップする。適用に衝突が 起こると、処理はそこでストップする。すでに適用してしまった部分は そのまま生かす。(XXX: ほんと?)

引数は複数指定することができ、この場合引数の順序で上記を実 行する。引数を指定しなかった場合には、デフォルトバージョンが指定 されたのと同じ動作をする。

適用元のチェンジセットが存在するバージョンは、プロジェクト ツリーとの間で共通の祖先を持つ必要はない。これは update と大きく 違うところである。また適用前にプロジェクトツリーにプリスティン以 降に加えられた修正分を退避しないのも update と異る。

他人のバージョンの一つまたは少数のチェンジセットを replay コマンドを使って選択的に適用することを、「チェリーピックする」と 言う。おそらく、イチゴ狩りならぬ、さくらんぼ狩り、みたいなイメー ジの言葉だと思うのだが、実際に聞いたことはない。誰かのシャレた言 葉の説明を本人に求めるほどヤボなことはない。

tla update

これは replay よりも概念的には上位にあるコマンドだ。引数の 与え方は、完全に省略する場合、バージョンを指定する場合、リビジョ ンを指定する場合の三通りがあるのは replay と一緒だが、その意味合 いは大きく異る。

まず、いずれの場合でも、update は実行に当たって、プロジェ クトツリーに対して tla undo を内部的に実行する。つまり直近のリビ ジョンにプリスティンの内容を使って戻る。それから引数の内容に応じ たチェンジセットの適用を実行し、最後に退避しておいたチェンジセッ トを tla redo でもう一度適用するのだ。

引数をなにも与えないと、デフォルトバージョンが指定されたも のと仮定する。バージョンを与えた時の動作は、まずプロジェクトツリー のデフォルトバージョンと、指定したバージョンとの共通の祖先をチェッ クする。共通の祖先とは、この二つのバージョンが分岐した最後のリビ ジョンを言う。そのようなリビジョンが存在しなければ、つまりふたつ のバージョンの起源が異っているなら、update はエラー終了する。こ のとき、共通の祖先より後に引数で指定したバージョンに追加されたチェ ンジセットを古いものから順にプロジェクトツリーに追加していく。引 数に指定したバージョンやプロジェクトツリーのデフォルトバージョン が継続によって作成されたものである場合には、その祖先のバージョン までさかのぼって共通の祖先を調べることに注意すること。どこかで衝 突が起こった場合にはそれまでのすべての適用を含めて処理を完全に取 り消す。プロジェクトツリー内のパッチログを確認して、重複マージを 避けるのは replay コマンドと同様である。

引数にリビジョン名を指定した場合の動作もバージョンを指定し た時と同様だが、そのリビジョンよりもリビジョン番号の大きなチェン ジセットは適用しない。

もし君が誰かの別のバージョン、例えば A/C--B--V--R からの分 岐を A1/C1--B1--V1 という形で作ったあと、このバージョンについて 行くには、自分の変更を A1/C1--B1--V1 に追加していき、ときどき tla update を A/C--B--V という引数で実行すれば、君が分岐した後彼 が加えた修正点のすべてを A1/C1--B1--V1 に取り込むことができる。

tla star-merge

このコマンドはマージ系コマンドの最上に位置するもので、大抵 のマージはこのコマンドを使えばうまくいく。初心者はマージにはいつ もこのコマンドを使うと良い。正確なアルゴリズムは以下のように非常 に複雑だが、利用は簡単だ。原始的なコマンドを組み合わせることで高 度な機能を実現するという GNU arch のコンセプトから行くと、tla を ラップする形で外部コマンドとして実装しても良いほどマクロなコマン ドだ。

このコマンドは、引数として指定した FROM リビジョンとバージョ ンREFERENCE との間の「一番近い共通祖先」にあたるリビジョンを計算 し、それと FROM との差分をプロジェクトツリーに適用する。 REFERENCE を指定しなければプロジェクトツリーのデフォルトバージョ ンを指定したものとみなすが、通常はこれで十分だ[14]。 これだけの話だが、問題は何をもって「一番近い共通祖先」=M.R.C.A とみなすかである。これがすこし複雑になる。

まずはこの計算に必要な登場人物を整理する。

表 5.1. 登場人物

アイテム要素種別意味
FROMリビジョン マージしたいリビジョン。バージョンが指定 された場合は、その中にある最新のリビジョンが指定されたと みなす。
FROM-Vバージョ ンリビジョンFROM が属するバージョンのこ と。
TREEプロジェク トツリー適用先のプロジェクトツリー。
REFERENCEバージョ ンマージの観点を示す。指定しなければ TREE のデフォルトバージョンが指定されたとみなす。
MAYBE_ANCESTOR_1 リビジョンM.R.C.A.の第一候補。 これはもし存在すれば FROM-Vに属する。
MAYBE_ANCESTOR_2 リビジョンM.R.C.A.の第二候補。 これはもし存在すれば REFERENCE に属する。
LAST_MERGE_INTO_FROM リビジョン計算途中で必要になる FROM-Vに 属するリビジョン。

MAYBE_ANCESTOR_1 は FROM リビジョン中にある、FROM-Vに属す るパッチログのうち、TREE に取り込まれた一番最後のものとして定義 される。たとえば、FROM が A/C--B--V--patch-10 だとすれば、このリ ビジョンは A/C--B--V--base-0 ... A/C--B--V--patch-10 のすべての パッチログだけは最低限必ず含むが[15]、このうち TREE に存在するものが A/C--B--V--patch-3 と A/C--B--V--patch-7 であれば、この後者が MAYBE_ANCESTOR_1 になる。どれが選択されるにせよ、FROM-Vに属する リビジョンで FROM リビジョンそのものか、それ以前のリビジョンにな ることに注意。条件にあてはまるパッチログが一つも存在しなければ、 MAYBE_ANCESTOR_1は存在しない。

MAYBE_ANCESTOR_2 は REFERENCE 中のリビジョンのうち、FROM リビジョンに取り込まれたもので一番後のものとして定義される。条件 にあてはまるパッチログがリビジョン FROM に一つも存在しなければ、 MAYBE_ANCESTOR_2 は存在しない。ところでリビジョン FROM は FROM-V に属するパッチログの他にもチェリーピックなどによって他のバージョ ンのパッチログも含むのが普通であることに注意してほしい。この事実 により REFERENCE と FROM が属するバージョンが異っている場合でも FROM リビジョンが FEFERENCE バージョンに属するリビジョンのパッチ ログを含むことはあるのだ。

LAST_MERGE_INTO_FROM は MAYBE_ANCESTOR_2 が存在する場合に 限って定義される。これは MAYBE_ANCESTOR_2 を最後にマージした FROM-Vのあるリビジョンを示す。FROM リビジョンが MAYBE_ANCESTOR_2 をパッチログとして持つので、LAST_MERGE_INTO_FROM は FROM そのも のか FROM以前の FROM-Vに属するリビジョンであることに注意すること。

以上を前提として、M.R.C.A. は以下のようにして求める。まず MAYBE_ANCESTOR_1 と MAYBE_ANCESTOR_2 が共に非存在の場合には M.R.C.A.は定義されず、star-merge は何もせず終了する。どちらか一 方が存在する場合には存在するほうのリビジョンとして定義される。両 方存在する場合には、まずMAYBE_ANCESTOR_1 とLAST_MERGE_INTO_FROM の順序関係が比較される。両方共 FROM-V に属するリビジョンなのでこ の比較は常に意味を持つ。MAYBE_ANCESTOR_1 の方が大きければ、 M.R.C.A. は MAYBE_ANCESTOR_1 と定義される。そうでなければ M.R.C.A. は MAYBE_ANCESTOR_2 とされる。あとは冒頭の差分を求め、 結果を TREE に適用する。これが star-merge の動作のすべてである。

パッチログの限界

あるプロジェクトツリーを考える。プロジェクトツリーはいままで 自分自身に適用されてきたチェンジセットのログであるパッチログを記録 している。これらのパッチログの由来について、すこし詳しく考えてみよ う。

パッチログは大きくいって二つのことに由来する。ひとつはこのプ ロジェクトツリーをどこかのバージョンに — 通常はデフォルトバー ジョンに対してということになるが — コミットしたような場合で ある。この場合、そのコミットが作り出した新しいリビジョン名に対応し たパッチログがプロジェクトツリーに追加される。一方アーカイブの対応 バージョンには、一つ前のリビジョンと今回作り出されたリビジョンとの 間の差分であるチェンジセットが新しいリビジョン名で作られるが、この 中にもいま問題にしているパッチログが追加される。tla get でこの最新 リビジョンを get すると、いま作り出されたばかりのパッチログも一緒 にプロジェクトツリーに含まれることになる。

パッチログのもう一つの由来は、今回プロジェクトツリーがコミッ トしようとしているバージョン以外のバージョンからのチェンジセットを このプロジェクトバージョン中にマージすることに由来している。たとえ ば今、A/C--B--V--R にいて、これとは別のバージョン中のリビジョンで ある A1/C1--B1--V1--R1 をマージしたとする。これは直接 replay コマ ンドで選択的に取り込んだのかも知れないし、それを含むようなもっと総 括的なマージの一貫として取り込まれたのかも知れない。いずれにせよプ ロジェクトツリーには A1/C1--B1--V1--R1 のパッチログが追加される。 そしてこのパッチログは、A/C--B--V--(R+1) のコミットで作られるチェ ンジセットに記録され、チェンジセットはアーカイブバージョンに追加さ れるので、アーカイブ領域にも記録されることになる。

ここからは議論を簡単にするため、コミットするバージョンに関係 したA/C--B--V--R のようなリビジョン名を P と表すことにし、コミット バージョン以外のバージョンからのチェリーピックを p, q, r, ... と表 すことにする。P に含まれているのは、プロジェクトツリーに対するマー ジコマンドの適用による、p, q, r, ... のパッチログと、自分自身のパッ チログだ。一方 チェンジセットとしての P の実際の内容は、p, q, r,.. の実際の内容と、P 自身の修正内容になる。マージコマンドだけを実行し たのであればこれは空だが、エディタなどで直接プロジェクトツリーのファ イルを修正した場合には空ではない。だから P = P + p + q + r ... となる(XXX: ひどい説明だ!)。

ものごとには順序に関係したことと関係しないことがあることの例

ここでの問題は、P に適用された P, p, q, r,... の順序が不明だ ということ、また P はアトミックではないということだ。たとえば foo.txt の先頭の方にある行を追加し、p, q, r を適用し、その後 この三つのチェンジセットで追加された行の一部を削除したような場合を 考えると、P という内容がはっきりしなくなってしまう。

問題は他にもある。たとえば p を適用した後、その適用を完全に 取り消すような修正をプロジェクトツリーに手で加えてからコミットすれ ば、パッチログには p が適用されたという情報が残るにもかかわらず、 実質的に p は適用されていない。

まだある。p, q, r の適用順序をパッチログは示していない。p, q, r の順序で適用されたのかも知れないし、q, r, p だったのかも知れ ない。チェンジセットの代数は一般的にはアーベル的ではないので、両者 の結果は異なったものになることもあるのだ。

結論として、パッチログはパッチ適用の履歴についての完全な記述 ではないということになる。これはせいぜいあるチェンジセットがすでに 適用されているかどうかの目安にすぎない。だから場合によってはパッチ ログを操作して、まだ適用されていないチェンジセットがあたかも適用さ れていたり、実際にはすでに適用されたかチェンジセットがあたかもまだ 適用されていないかのようにプロジェクトツリーを「だます」必要がある。 こんな事態は頻繁におこるわけではないが、時には必要になる。GNU arch はもちろんこんな場合にそなえていくつかのコマンドを用意している。 tla add-log-version, tla remove-log-version, がそれである。

パッチログエントリを追加・削除するコマンドは存在し ないのか? またこれは現実の場面では不要なのか?

マージの失敗が意味すること

マージの失敗はプロジェクトツリーにのみ関係しているので大きな 問題にはならないことの説明。元に戻すための操作についての説明。



[14] プロジェクトツリーはどれか一つのバージョンに結び付いているわけで はないことに注意しよう。詳しくは XXX 参照。

[15] なぜこう言えるの だろう? プロジェクトツリー中でコミットが成功する条件としてGNU arch が課している制約を思い出してくれればわかると思う。考えてみ てほしい。

第6章 最適化

この章では、GNU arch が必要なリビジョンやチェンジセットを高 速に取得する方法について議論する。この章での議論はパフォーマンスに 関してのことだけで、ここを読んでも本質的に何か新しい機能がつけ加わ るわけではないし、基本的な設定をすませてしまえば、普段はあまり意識 しないでこの恩恵にあずかることができる。普通免許さえあれば、誰でも ベンツにも乗れるのと一緒だ。しかしある特定のバージョンの中に非常に たくさんのリビジョンを蓄積していく場合や、ネットワーク上の別のマシ ンにあるバージョンとのやりとりが発生するような利用が主な場合、ここ での技法は場面によっては速度を劇的に改善することがある。GNU arch を実践的に利用しようと考えているなら、いつかはこの章のどれかの技法 が君を助けることになるだろう。誰だって料金がそんなに違わないなら ファーストクラスで行くだろう。

リビジョンキャッシュ

ひとつのバージョンに対して新しいリビジョンをコミットするたび、 バージョンの中にはそのリビジョンを直前のリビジョンから作り上げるの に必要なチェンジセットが蓄積されていく。tla get などのコマンドで最 新リビジョンを取得する場合、リビジョンが大きい程長い時間がかかるが、 これはベースリビジョンに対して適用しなくてはならないチェンジセット の個数がリビジョンの数に比例して大きくなっていくからだ。tla get が 表示するメッセージを見てもこれは明らかだろう。

$ tla get C--B--1.0
* from import revision: octopus@bluegate.org--2004/C--B--1.0--base-0
* patching for revision: octopus@bluegate.org--2004/C--B--1.0--patch-1
…
* patching for revision: octopus@bluegate.org--2004/C--B--1.0--patch-238
* patching for revision: octopus@bluegate.org--2004/C--B--1.0--patch-239
* making pristine copy
* tree version set octopus@bluegate.org--2004/C--B--1.0
$

patching for revision: で始まる行が直前のリビジョンに対して 次のチェンジセットを内部的に適用していることを示す行だが、これはも ちろんリビジョンが上がっていくにつれて増える。リビジョンを一から計 算しないで適当なリビジョン間隔でキャッシュしておけばリビジョンの取 得は早くなる。これをリビジョンキャッシュと言う。たとえば patch-50 patch-100, patch-150, patch-200 のリビジョンのキャッシュを保持して いれば、たとえば patch-239 を取得する場合には patch-200 からの計算 だけを考えれば良いことになるからだ。リビジョンキャッシュを作るには tla cacherev コマンドを使う。このコマンドはあるリビジョンの内容を tla get と同じアルゴリズムで計算し、アーカイブ中の、本来チェンジセッ トしか保持していないリビジョンの、リビジョンの内容全体を保存する。

あるバージョンが、別のバージョンからの継続として作られた場合 ベースリビジョンをキャッシュするのは広く行なわれる最適化だ。こうし ないと継続先のリビジョンを tla get しようとすると、継続元のバージョ ンにまで遡ってリビジョンを構築することになってしまう。継続元がネッ トワークをまたいだ別マシン上にある場合にはこの違いはより顕著になる のは明らかだ。

あるリビジョンに対するリビジョンキャッシュは、バージョン中の チェンジセットのサイズがごく小さいものだと仮定すれば、大体ベースリビジョ ンと同じ程度の領域を食うので、たくさんのリビジョンについてキャッシュ するのはあまり得策ではない。こんな場合にはリビジョンライブラリを構 築する方が良い結果が得られるだろう。

アーカイブ・ミラー

アーカイブ・ミラーは、あるアーカイブを別のアーカイブにそっく りそのままコピーしたものだ。GNU arch のアーカイブはネットワーク透 過性を持っていることを思い出してほしい。つまり同じマシンの上にある 二つのアーカイブ間でできることは、異るマシン間にあるアーカイブに対 しても必ずできる、という GNU arch の設計上の大原則だ。この性質を利 用すれば、アーカイブ・ミラーのソースとディスティネーションを別マシ ンに設定して、たとえばソースをリモートアーカイブ、ディスティネーショ ンをローカルアーカイブとすることも、その逆も、また両方を同じマシン 上の異るアーカイブとすることもできる。最初の場合はリモートアーカイ ブからローカルアーカイブへのコピーとなる。二番目はその逆になる。最 後のケースは何の役にたつか不思議に思うかも知れないが、たとえば一方 のアーカイブは外部に公開していない、プライベートなもので、もう一方 は公開しているアーカイブだとする。そして普通はプライベートアー カイブ上のバージョンで作業をしていて、問題がないと確信した時点でそ の内容を公開アーカイブにも反映したいような場合、ローカルアーカイブ 間のミラーも意味をもつ。

ミラー先のアーカイブには自分がミラーであることを示す情報があっ て、tla import や tla commit を実行しようとするとエラーになる。tla archive-mirror コマンドを利用する以外に、ミラーアーカイブに書き込 みを行なうことはできない。

まず、いままで直接アクセスしていたリモートアーカイブのミラー をローカルに作り、このミラーにリモートアーカイブの内容を実際にミラー したあと、このミラーにアクセスする例を示す。実際のミラーには非常に 時間がかかることもあるが、いったん転送が済んでしまえば、アクセスは 飛躍的早くなるのが普通だ。Tom Lord のマスターアーカイブを使って説 明しよう。まず、Tom のアーカイブに直接アクセスするような形にアーカ イブを登録する。それから tla abrowse でこのアーカイブを閲覧してみ てほしい。かなり時間がかかるはずだ:

$ tla register-archive lord@emf.net--2004 \
      http://regexps.srparish.net/{archives}/lord@emf.net--2004
$ tla abrowse -A lord@emf.net--2004
…
$

次にローカルマシンにミラーを作るわけだが、tla make-archive コマンドを実行する前にアーカイブ名について少し考える必要がある。ミ ラーアーカイブに何という名前をつけるか、だ。lord@emf.net--2004 と いう名前はすでに Tom のマスターアーカイブとしてたったいま利用して しまっているので、同じ名前をミラーに対して利用することはできない。 普通はアーカイブ名の後ろに "-MIRROR" という文字列をつけた lord@emf.net--2004-MIRRORという名前を使うが、必ずそうしなくてはな らないという決まりはない。アーカイブ名の形式に従ったものならどんな 名前をつけても良い。で、考えてみてほしいのだが、今後このミラーには 頻繁にアクセスすることになり、あたかもこちらが Tom のマスターアー カイブだとみなしたほうが都合が良いだろう。こっちを lord@emf.net--2004 という名前でアクセスしたい。すると今度は Tom の オリジナルの方を別の名前で呼ぶ必要が出てくる。これももちろん可能だ。 あるアーカイブ位置をどんな名前で呼んでも GNU arch が動かなくなるこ とはない。結局、Tom のオリジナルを lord@emf.net--2004-SOURCE と呼 び、ローカルミラーをlord@emf.net--2004 と呼ぶことにする。

$ tla register-archive -d lord@emf.net--2004
$ tla register-archive lord@emf.net--2004-SOURCE \
      http://regexps.srparish.net/{archives}/lord@emf.net--2004
$ tla make-archive --mirror lord@emf.net--2004-SOURCE lord@emf.net--2004 
      /home/foo/{archives}/lord@emf.net--2004
$

tla make-archive の前に、tla register-archive で lord@emf.net--2004 の削除と、同じアーカイブ位置を lord@emf.net--2004-SOURCEという名前であらためて登録していることに 注意してほしい。それからミラーアーカイブを tla make-archive で作成 している。tla make-archive コマンドは内部的に tla register-archive の処理も一緒に行なうので、lord@emf.net--2004 はローカルミラーとし て登録される。次に実際にアーカイブの転送を行なう:

$ tla archive-mirror lord@emf.net--2004-SOURCE lord@emf.net--2004
…
$

これにはアーカイブの大きさにおうじて、通常は長い時間がかかる。 何か別のことをやっていた方がよいだろう。ミラーが完了したらもう一度 tla abrowse を走らせてみよう:

$ tla abrowse -A lord@emf.net--2004
…
$

おそらく劇的に早くなっているはずだ。いったんミラーをつくれば、 今後の tla archive-mirror は差分だけの転送になるのでそれほど時間は かからなくなる。この処理は cron でやらせるのがおすすめだ。私はもち ろん Tom のすべてのアーカイブを自分のマシンにミラーしているが、一 日一回ミラーするようにしている。これで Tom のマシンに何か恐ろしい ことが起こっても、私のミラーを使って最悪 24 時間前の状態にまでは戻 せる。分散システムならではのメリットだ。GNU arch コミュニティーに はこのようなバックアップ的な意味あいでのミラーを、もっと大規模に構 築しているメンバーもいる。詳しくはXXXを見てほしい。

ミラーの話しに限ったことではないが、あるアーカイブから別のアー カイブに対する継続がある場合、最低限、継続のリビジョンでは tla cacherev コマンドでキャッシュしたほうが良い。そうしないと、せっか くあるアーカイブをミラーしても、そこからリビジョンを get しようと すると、継続をさかのぼって結局は別のアーカイブも参照しにいくことに なり、そのアーカイブが登録されていないことでエラーになったり、登録 されていてもスピードの恩恵にあずかることができないことになってしま う。これはミラーされる側のエチケットかも知れない。もちろん誰も彼に そんなことを強要することはできないが。人はみな、自由なのだ。

もうひとつの例は、公開用アーカイブと、ブライベートアーカイブ とのミラーだ。XXX

ミラーの特徴は、ユーザが自発的にミラーする必要があることだ。 tla archive-mirror コマンドを時々実行しなければミラーの意味はない。 これにたいして次節のリビジョンライブラリは、ユーザが通常の操作を行 なう過程で自然とキャッシュされていような仕組みを持っている。ここが 違うところだ。用途や場面に応じて、どの方法が最適か、自分で考えてみ てほしい。

リビジョンライブラリ

最後の方法がリビジョンライブラリだ。まず最初に断っておくが、 リビジョンライブラリは、通常のコンピュータ言語での開発で利用するラ イブラリとは何の関係もないので注意してほしい。リビジョンライブラリ は大雑把にいって、アーカイブバージョン中のすべてのリビジョンを完全 な形ですべて保持してしまおうという考え方だ。ある意味非常に露骨でもっ とも単純で、それゆえ強力な方法だとも言える。すべてのリビジョンを展 開した形で持つわけだから、莫大なディスク容量が必要に思えるが、リビ ジョン間で変更のないファイルについては unix のハードリンクの考え方 を使い、一つの実体としてのファイルを複数の場所から指し示すことによっ て空間を節約する仕組みを持っている。もちろんこれは内部的な実装の話 なので利用者から見ると、巨大なリビジョン群がそのままそこに存在し、 その割にはディスクが消費していないような状況になる。あるリビジョン から次のリビジョンへの修正は通常それほど多くのファイルで起こるわけ ではないので、空間の最適化はかなり良い結果をもたらすことが多い。

リビジョンライブラリは、自分が必要だと思うリビジョンを明示的 に指定して生成することもできるし、ある処理において副次的にリビジョ ンを計算しなくてはならない時に、暗黙にそのリビジョンをライブラリに 常に追加するように設定することもできる。後者に設定しておけばいちい ち tla library-add コマンドを発行しなくても、いろいろなアーカイブ バージョンをいじっているうちに自然とパフォーマンスが向上していくよ うな結果をもたらすはずだ。欠点としては自分があまり意識しないうちに ディスク容量が消費されていくことだろう。

暗黙にリビジョンライブラリの内容を豊富にしていくのと同時にディ スク容量もそれほど消費させたくない場合、折衷案をとることもできる。 このためにもう一つ設定することのできるパラメータがある。この sparseを設定すると、あるリビジョンをライブラリに追加する際、そのリ ビジョンを作成するに当たってできた中間のリビジョンについてはライブ ラリに登録しない。

ライブラリを扱うコマンドはいろいろと存在するが、例によってカテゴリ・ブ ランチ・バージョンの 3 階層システムからくる複雑さであり、基本的に は設定、追加、内容表示、の 3 っつの種類しかない。

リビジョンの検索順序

すでに見てきたように、GNU arch はさまざまなキャッシュを持っ ていて、ある特定のリビジョンを取得する場合、可能であれば本来のアー カイブの場所から取得するかわりに、より時間的なコストが安い場所から 取得しようとする。ではそのような場所が複数あった場合にはどうするの だろうか? リビジョンの検索順序は以下のようになる:

  1. リビジョンライブラリを検索する。あればそれを利用 する。

  2. プリスティン・コピーを検索する。あればそれを利用 する。

  3. 最後にアーカイブを利用する。

リビジョンライブラリは複数の場所に保持することが可能で、この 場合にはリビジョンライブラリ自身の検索順序で検索される。プリスティ ンコピーを利用するのは tla get コマンドのオプションで明示的にパス を指定するような特殊な場合に限られる。最後にアーカイブを利用する場 合、アーカイブ中でそのリビジョンがキャッシュされていれば、それを直 接展開する。そうでなければ、最後のキャッシュリビジョン、またはイン ポート時の初期リビジョンを取得した後に、そのツリーに対して順次次の チェンジセットを適用して必要なリビジョンを求める。この最後の場合に は大雑把に言ってリビジョンの数に比例した時間がかかることになる。

アーカイブミラーの話が出てこなかったのは、tla get オペレーショ ンにおいてはミラーと通常のアーカイブを区別することはないからだ。ミ ラーハキャッシュの検索順序の議論よりも 1 レイアー低い場所でキャッ シュするしくみだと言うことができる。

第7章 新しい概念

この章では、従来のバージョン管理システムではあまり馴染みのな い概念について個別に説明しようと思う。基本的には GNU arch の基本的 な利用方法が身についたあとで理解を深めるためにゆっくり読んでもらう ことのできる章だが、運悪く初期インポートでつまづいてしまった時には 「インベントリ」の節だけはあらかじめ読む羽目になるかも知ない。チェ ンジセットはパッチの一般化であるので概念的には易しいと思うのだが、 何故か非常に難しく高尚な概念のように言われているようだ。パッチログ についてはまとまった文献として説明しているものをあまり見かけないの でできるだけ詳しく説明したいと考えている。

インベントリ

初期インポート時に、正体不明のエラーが表示されてどうしてもうまく行 かないことがある。これはたいていの場合、インポート対象としたいファ イルがうまく認識されていないか、ディレクトリ中に認識できないファイ ルが残っている場合だ。GNU arch はインポート時にもコミット時にも、 プロジェクトツリー全体をスキャンして、自分が認識できないファイルが 存在しないかどうかを確認する。どのようなファイルを認識できないもの にするかは、設定によってプロジェクトツリーごとにユーザが自由に設定 できるのだが、結果として認識できないファイルがディレクトリに残って いるとエラーを表示してコミットやインポートを中断する。これは、きち んと把握しているファイルのみがプロジェクトツリーには現れるべきだと いう GNU arch の思想を反映している。ただしこれには例外があって認識 できないファイルがあったとしても、それを認識できるファイルとみなす ように設定することもできるのだ。また認識できないケースにも二通りあっ て、ファイル名の形からくる場合と、インベントリidが正しく振られてい るかどうかからくる場合もある。また認識できるファイルは、諸事情でさ らにいろいろなファイルタイプに分類されているし、インベントリid 自 身の概念が通常のバージョン管理システムでは存在しないものであること などが理由で、ファイルタイプの認識ロジックは非常に複雑なものになっ ている。

ここでは GNU arch のファイル判別ロジックの詳細を説明する。もし初期 インポートにすでに成功していたり、分岐によってプロジェクトを始めた のであれば、すぐにこの章を読む必要はないと思う。しかし、新しいファ イルをプロジェクトに追加したとたんにコミットができなくなった、とか、 初期インポートがどうしてもうまくいかずエラーになる、という場合には、 この章を読んで、GNU arch のファイル判別ロジックについて少し詳しく 考える必要があるかも知れない。根底にある理屈がわかってしまえば、た いていのエラーは解消すると思う。一点だけ注意だが、GNU arch の場合、 新しいファイルをプロジェクトに追加する場合、CVS など他のバージョン 管理システムにあるような明示的なファイル追加コマンドは存在しない。 インポートまたはコミット時のファイルスキャンで規則に合致すればそれ は追加されたファイルになるし、合致しなければそうはならない。そして 運悪くそれが認識不能ファイルに最終的に分類されればインポートやコミッ ト自体が中断されてしまう。それだけの話だ。

ところで、私は語学が苦手だ。たとえば英語。わけのわからない規則が多 すぎる。want の過去形は wanted だからということで、go の過去は goed だというと笑われる。一個と二個以上を区別するくせに、二個と三 個は区別しない。三人称単数現在に限って動詞の最後に s をつける。で 得意になって studys なんてやるとまたバカにされる。ラテン語なんて最 悪だ。名詞には6っつも格があって、おまけに性がある。海がどうして女 性名詞なのか教えてほしい。人魚が住んでるからだろうか? でも海坊主だっ てちゃんと住んでる。「バラ」は女なのに、「花」は男だと言う。わけが わからない。結局、こういうのは丸暗記するしかないのだ。

GNU arch にもよく似たところがある。もちろん、作者はご存命だし、も う少しは合理的にできているし、ほりさげていけば、いちいちちゃんとし た理由もあるのだろう。でも、悪いことは言わない。最初はあまり深く考 えないほうがいい。そういうものなんだと割り切ろう。

ルールその1:   GNU arch はファイルを以下の xxx 種類にとりあえず分類するという約束がある。   これを一次分類と呼ぶ。 ルールその2:   一次分類は、ファイル名の形だけをもとにして分類される。 ルールその3:   一次分類でソースと見なされたファイルはインベントリidの存在/非存在   によってさらにソースかどうかを判断されるこれを二次分類という。   二次分類でソースでないことがわかったファイルは、とりあえず非認識とされる。 ルールその4:

  

この結果、最終的にファイルが非認識とみなされれば、インポートやコミッ トは中断される。これを防ぐには、ファイルタイプをソースとなるように =tagging-method を書き換えてから、必要に応じてインベントリidをこの ファイルにつける。つける方法は・・・・ファイルの個数が多い場合、こ れを手でやるのは大変だ。たとえばすでに別のバージョン管理システムで 管理していたファイルを GNU arch に移行したいような場合だ。ありがた いことに自動的にインベントリidを振ってくれるツールを作成している人 たちもいる。詳しくは・・・を見て欲しい。インベントリid については 次の節で詳しく説明しようと思う。GNU arch にしか現れない重要な概念 の一つだ。

ここでの議論は退屈で、見通しがわるく、しかも運が悪いと、GNU arch の使い始めから理解しなくてはならない場所になってしまう。それほど unix に詳しくない人なら、多分ここでさようなら、だろう。このシャー プな学習曲線を緩くするうまい方法は見つけることは、GNU archにとって 急務だと考えている。

インベントリとは、一言で言うと「バージョン管理下にあるそれぞ れのファイルの由来を示す識別子の一覧」のことだ。あるファイルが GNU arch 管理下に置かれるには次の二つのどちらかのケースしかない。一つ は、新しいバージョンをアーカイブにインポートする時にインポート対象 になっている場合。もう一つは、すでに存在しているリビジョンから分岐 したバージョンを作った場合だ。最初の場合には GNU arch システムから 見た時にはそのファイルは新規に導入されたので、新しい識別子が必要に なる。後の場合にはすでにあるファイルと由来を同じくするファイルがで きたので、識別子は分岐元のファイルと同一のものになる。分岐した後、 一般には両方のバージョンで、二つのファイルは独立に変更されていくだ ろう。その独立した二つのファイルには同じインベントリidが振られてい るので、ファイルの自己同一性を示すというよりは、ファイルの由来の同 一性を示す識別子である、と理解するのが正しいだろう。

インベントリの考え方自体は非常に単純なものだ。インベントリ の問題を複雑にしているのは、既存の Unix 系ファイルシステム上でイン ベントリを実装しようとするのが難しいことと、GNU arch のファイル分 類機構と一部干渉する部分があるからだ。GNU arch の初期インポート に失敗する場合、ファイル分類機構がエラーを出している場合と、インベ ントリの仕組みがエラーを出している場合がありこの判別が難しいのだ。 本来、ファイル分類機構はインベントリとは何の関係もない話だが、あ えてこの節で一緒にとりあげることで、初期インポート時のトラブルへの 対処方法を示したいと思う。初期インポートという、一番最初の操作 でつまづく可能性があるのは GNU arch の普及をさまたげる大きな原因の 一つになりかねないのは残念なことだ。

チェンジセット

第1章の議論を思い出してほしい。私はバージョン管理手法の最も 原始的な形態としてのバックアップを取り上げ、それからテキストファイ ルに対する差分管理について述べた。バックアップをとるかわりにファイ ルの差分をつぎつぎと保存していけば十分であるという議論だった。チェ ンジセットはこのひとつのファイルに対する差分を、ディレクトリツリー 全体に対する差分へと拡張したものだ。だからチェンジセットのことをパッ チと呼ぶ人もいる。ちょっと考えると、これはわざわざ鳴り物入りで言う ほどのことではないような気もする。ファイルが N 個あるのなら、ファ イルごとに管理した N 個の独立した差分を考えれば十分ではないか、と。 GNUdiff を使ったことのある人なら、-r オプションつきで実行すれば、N 個の独立した差分を一つのファイルとして表現することすらできると思う かも知れない。しかしここに罠がある。

まず、パッチファイルには、ファイルの生成、消滅を厳密に扱う方 法がない。GNUdiff を使って同等のことを表現しようとすると、ファイル の生成は、ゼロバイトのファイルと、生成後のファイルの差分を作る形で 表すしかないし、消滅の場合には、消滅前のファイルの内容と、ゼロバイ トのファイルのファイルの差分を計算する形で表すより他ない。-N とい うオプションはこれを実行してくれる。しかしこれでは、その時点でファ イルが生成されたことと、実はゼロバイトで存在していたことを区別する ことができない。消滅の場合も話しが逆になるだけで同様である。

次に、パッチファイルはファイルのパーミッションの変化について 記録する方法がない。あるシェルスクリプト foo.sh に、うっかり実行権 限をつけるのを忘れたとする。あるリビジョンで内容には一切変更を加え ず chmod +x foo.sh のようなことをやって実行ビットを立てたとする。 パッチファイルにはこのような変化を記録する方法がないのだ。他にもま だある。ファイル名称の変更だ。あるファイル、./foo.h を、./include/foo.h に移動したとする。パッチファイルではこれを表現できない。あるファイ ル ./foo.h がある日突然ゼロバイトになり、./include/foo.h というゼ ロバイトのファイルが、突然 ./foo.h の内容になったようにしか表現で きない。これは都合がわるい。すでに述べたように、我々はファイル名の 変更を追うための強力なしくみ、インベントリを手にしているのだ。これ を生かさない手はない。しかしパッチファイルにはそれができない。

そんなこんなで、パッチの拡張であるチェンジセットのデータ構造 が厳密に定義された。チェンジセットはパッチが一つのファイルであるの に対して決まった名前のファイルと構造をもつディレクトリとして定義さ れる。これはチェンジセットを扱う GNU arch の内部ロジック、 dopatch()/mkpatch()が、このデータ構造中でランダムアクセス処理が発 生するためだ。パッチファイルはただのファイルなのでもちろんバイト列 が並んだシリアル形式のデータ構造だ。だからランダムアクセスには向か ない。しかし、これは単なる実装上の問題でしかない。チェンジセットが ディレクトリであることには本質的な意味は何も無い。

チェンジセットの厳密なデータ構造は補遺に示した。興味のある方 はご覧いただきたい。

パッチログ

プロジェクトツリーが他のバージョンからのチェンジセットを適用 すると、「そのチェンジセットはもう取り込んだ」という意味のログが、 {arch}管理配下に記録される。これをパッチログと言う。パッチログは通 常のファイルで、中には RFC822形式に準じたいくつかの情報があり、人 間への手がかりとなるが、GNU arch がシステム的に考慮するのは「パッ チログが存在するか、否か」だけだ。つまり管理領域に A/C--B--V--R が 存在すればこのチェンジセットはすでに受け取っているのであり、存在し なければ受け取ってはいない。それだけだ。プロジェクトツリーをコミッ トすると、パッチログはアーカイブバージョン中のチェンジセットにも記 録され、永続的なものとなる。

GNU arch のマージコマンドは常に、マージするチェンジセットが すでにパッチログとして記録されているチェンジセットと一致しないかど うかを確認し、パッチログが存在しない場合に限りそれを適用する。これ によって同じチェンジセットを二度以上適用してしまう、いわゆる重複マー ジの問題を回避することができる。

パッチログはチェンジセットにも含まれるが、その当のチェンジセッ トに対応したパッチログだけではなく、そのチェンジセットが間接的に受 け取ったパッチログも含んでいる。たとえば C1--B1--V1--R1 というリビ ジョンで、Cx--Bx--Vx--Rx と、Cy--By--Vy--Ry という 二つのパッチログを受け取り、C1--B1--V1--R1+1 というリビジョンをコ ミットしたとしよう。するとチェンジセット C1--B1--V1--R1+1 には、 この三つのチェンジセットに対応したパッチログがすべて含まれる。 このチェンジセット C1--B1--V1--R1+1 を受け取った Cz--Bz--Vz--Rz+1 には、自分自身もふくめて四つのパッチログをプロジェクトツリーに追加 することになる。このようなパッチログの授受の連鎖によって、一度適用 したチェンジセットを、もう一度同じバージョンから受け取ることを回避 できるだけではなく、めぐりめぐって別のバージョンから受け取ることも 回避できる。

コミットとパッチログとの間の関係パッチログの不完全性の説明パッチログを調整するコマンドの説明

継続

どんなバージョン管理システムにも共通の、当たり前の原則がある。 それは過去に現れたデータは決して削除されない、というものだ。データ を削除する、とは、削除された形の新しいリビジョンを「追加」する、と いうことでしかない。過去は消せない。髪を黒く戻して、ピアスを外して タバコを辞めても、タイムマシンに乗ればバレてしまう。

アーカイブ中で、リビジョンがコミットされるにつれ、データは増 えていく。過去のデータは古くなるにつれ、監査や考古学的な興味を除け ば、その価値は薄れていく。もし、新たらしい部分のリビジョンを取得す るのに過去のリビジョンに強く依存しているとすると、これは問題がある。 たとえばディスク障害が起こって、非常に古いリビジョンのほんの一部が わずかに壊れてしまったとしよう。これが理由で、アーカイブ中のすべて のリビジョンのデータが全滅したとすれば、それはまずい。腐ったリンゴ を簡単に捨てちゃいけない。腐った部分だけ捨てて、腐ってないところを おいしくいただきたい。

GNU arch はちゃんとこのへんの事情を心得ていて、あるアーカイ ブバージョンのリビジョンが増えたら、別のバージョンに乗り移ることが できる。これを継続という。私は何か新しいことを書いているようだが、 実はこれは tla tag コマンドで分岐を作る行為そのものだ。だから分岐 には実は二通りの、すこし異なるニュアンスがあることがわかる。一つは 幹の開発をさまたげずに自分独自の修正を加えるための分岐。もう一つは リビジョンが大きくなりすぎたのでアーカイブバージョンをここらで新し くしたいと思って始める分岐。つまり継続。継続を作ったら、そのベース リビジョンはキャッシュしておくことを強く勧める。これで過去の分岐元 のバージョンが腐っても、継続後のバージョンは被害を受けることはない。

継続バージョンを作ると、継続後のバージョンは自分の継続した祖 先のバージョンを記憶している。tla ancestry コマンドはこの情報を元 にしてあるバージョンの祖先をずっとたどってくれる。しかし逆はだめだ。 あるバージョンの親は、自分にどのような子がいるか知らない。子供を列 挙する方法はないのだ。無理にやろうとすれば、たとえばあるアーカイブ 中をしらみつぶしに検索することになるだろう。これは現実的ではない。 それに特定のアーカイブ中でしかこれはできない。しかし地球上には無数 のアーカイブがあるのだ。この非対称性は、親に黙って分岐を作ることが できる、という GNU arch の性質に対応している。もし親が子の情報をも つとすれば、黙って分岐を作ることができなくなるだろうが、それじゃブ ルーな世界に逆戻りだ。

第8章 サインつきアーカイブ

うる覚えなのだが、GNU の初期のサーバにはパスワードが振ってい なかったそうだ。パスワードのないサーバが単にインターネットにぶら下 がっていた。信じられないが本当らしい。過去にさかのぼればさかのぼる ほど人間は素朴で素直で満ち足りていたというルソー的史観には常に胡散 臭いものを感じてしまうが、ことコンピュータの歴史に関して言えば、当 たっている部分もあるのかも知れない。インターネット上の雰囲気もずい ぶん変わってしまった。いまではセキュリティーを考えることなしにどん なソフトウェアについても語ることはできなくなってしまった。GNU arch も tla-1.2 からセキュリティーを考慮するような仕組みが追加された。 この章ではアーカイブに対して署名をつける方法について説明する。 署名は任意のアルゴリズムが利用できるが、現実には pgp を利用するこ とが多い。ここではこの具体例についても説明する。

チェックサムの計算

アーカイブには署名することができて、この機能を有効にするかど うかはアーカイブごとに選択することができるが、サインするしないにか かわらず、アーカイブに新しいデータが追加される時にはかならすその追 加データに対するチェックサムが計算され、独立したファイルとして同時 に保存される。アーカイブに対する追加は以下のどれかのコマンドでしか 発生しない。つまり、import, commit, tag, cacherev である。 [16] 追加データが正しい内容であるかどうかは追加データのチェックサムをも う一度計算し、チェックサムファイルの値と一致するかどうかを確認する ことで検証することができる。ディスクの低レベルエラーや、作為的でな いデータ検証はこれでおこなうことができる。

サインつきアーカイブ

チェックサムの計算だけでは、作為的な悪意のある改懺からデータ を守ることはできない。チェックサムを計算する元データを変更して、そ れに対するチェックサムを計算し、元のファイルとそれぞれ置き換えれば チェックサムの妥当性検証をすり抜けることができる。これを防ぐために はアーカイブをサインつきとして設定する必要がある。サインつきアーカ イブのアイディアは非常に単純である。前節で説明したチェックサムファ イルに対してなんらかの暗号方式で署名するだけである。これで追加デー タを別の悪いあるもので置き換えたあとチェックサムを計算することはで きても、そのチェックサムに正しい署名をすることは本人にしかできない ので結果的にデータの改懺は不可能になる。

サインつきアーカイブを作るには、tla make-archive で --sign オプションをつけて作成するだけでよい。これはアーカイブをとにかくサ インつきとすることを指示するだけであって、具体的にどのような暗号方 式を利用するかを決めるものではない。具体的なサインの仕方は、

~/.arch-params/signing/アーカイブ名

というファイルに実際のサインの仕方を示す単一のシェルコマンド を指定する。典型的には、たとえば octopus@bluegate.org--2004 をサインつ きアーカイブとして作成したあと

~/.arch-params/signing/octopus@bluegate.org--2004

という通常のファイルを作り、その中に

gpg --clearsign

のように書く。gpg は GnuPG と呼ばれる pgp の実装である。gpg そのものの説明や設定方法はこのドキュメントの範囲を越えている。

http://www.gnupg.org/

のページなどを参考にしてほしい。主要な unix 系 os であれば パッケージに含まれていることが多いのでインストールは容易だと考えら れる。

指定するプログラムは標準入力からチェックサムファイルの内容を 受け取り、標準出力に対してサインした結果を返すような任意のプログラ ムを設定することができる。たとえば上の例では、gpg プログラムはパス フレーズと呼ばれるパスワードを起動のつど対話的に聞いてくる。つまり import, commit, tag, cacherev のようなコマンドを実行するたびにパス ワードを入力しなくてはならない。これは頻繁にコミットするような環境 では不便なので、パスワードをキャッシュするようなプログラムもある。 たとえば agpg と呼ばれるようなプログラムは一度だけパスフレーズを入 力するとそれ以降はメモリ中にその内容をキャッシュしておいてくれるも のだ。このようなプログラムを使う場合には、

~/.arch-params/signing/octopus@bluegate.org--2004

という通常のファイルの内容は

gpg --clearsign

のかわりに

agpg --clearsign

のような設定になる。こちらについても詳しい説明は agpg のサイ トを参照してほしい。

サインつきアーカイブのチェック

前節はサインつきアーカイブの作成方法と、それに対する具体的な サイン方式の設定についての方法だったが、逆にサインつきアーカイブか ら取得したデータの妥当性の検証方法の設定の仕方について説明する。こ ちらのほうは

~/.arch-params/signing/octopus@bluegate.org--2004.check

のような通常ファイル、つまりチェック方法を設定したいアーカイ ブ名の後に .check の拡張子をつけたファイルに、チェック方法を示すシェ ルコマンドを記述することでおこなう。典型的には

gpg --verify-files -

こちらについても、標準入力からテキストを入力し、その結果をス テータスで返すようなプログラムであれば何でもよい。しかし現時点では 上記のようなコマンドを設定するのがほとんど唯一の現実的な利用方法で あると考えられる。

デフォルトルールの設定

サインつきアーカイブの数が増えてくると、いちいち前節や前々節 の方法ですべてのサインつきアーカイブの設定をするのは大変である。特 に指定していないアーカイブについてのデフォルトルールが設定できると 便利だ。これには、実際のサイン、その検証それぞれのシェルスクリプト を

サインのルールのデフォルト
~/.arch-params/signing/=default
サインのチェックルールのデフォルト
~/.arch-params/signing/=default.check

にそれぞれ設定する。現実的な利用方法としては、もっとも保守的 に、つまり安全に運用する場合は、それぞれ:

gpg --clearsign
gpg --verify -

と設定する。またもっともリベラルに、つまりサインもしないし チェックもしない場合には、両方のファイルをゼロバイトのファイルとし て作成すると良い。



[16] ところでアーカイブから例外的にデータを削除するコマ ンドがひとつだけある。uncacherev である。

第9章 フックとレシピ集

この章ではフックスクリプトと、よく利用される GNU arch のレシ ピについて説明する。

フック

ある種の重要なできごとが起こった時に、それに連動する形であら かじめ登録しておいた処理が実行されると都合がよいことがよくある。こ のような処理をフックと言う。これは別に GNU arch に限った話ではない。 ソフトウェアに限った話ですらない。腰にぶら下げる万歩計を考えて見れ ばいい。足を一歩踏み出すたび、万歩計はカウントされる。これは足を一 歩踏み出すという行動に対するフックだと言える。フックには二つの要素 がある。ひとつはフックのトリガーとなる出来事、もう一つはフックの内 容だ。出来事のことをフックイベントと呼んだりする。

GNU arch でのフックイベントは以下のとおりである:

表 9.1. フックイベント一覧

フックイベントイベントの意味とタイミング
make-archive新しいアーカイブが作成された直後に発生
make-category新しいカテゴリが作成された直後に発生
make-branch新しいブランチが作成された直後に発生
make-version新しいバージョンが作成された直後に発生
precommitコミット直前に発生
commitコミット直後に発生
importインポート直後に発生
tag分岐作成の直後に発生

実際に呼び出されるフック用のプログラムは、 ~/.arch-params/hook である。どのイベントが起こった時でもこのプログ ラムが呼び出される。~/.arch-params/hook は実行可能ビットが設定され ている必要がある。

~/.arch-params/hook は唯一の引数をとり、これは上記で列挙した フックイベント文字列そのものである。たとえばコミット直後には:

~/.arch-params/hook commit

という形でフックが呼び出される。フックスクリプト中で引数の内 容によって分岐するようなシェルスクリプトにすることで各種フックイベ ント用の処理を切替えることができる。さらに必要に応じてフックは以下 の環境変数が設定された状態で呼び出される。

表 9.2. 設定される環境変数一覧

環境変数説明
ARCH_ARCHIVE 
ARCH_CATEGORY 
ARCH_BRANCH 
ARCH_VERSION 
ARCH_REVISION 
ARCH_LOCATION 
ARCH_TREE_ROOT 
ARCH_TAGGED_ARCHIVE 
ARCH_TAGGED_REVISION 

以下は hook ファイルの例である:

#!/bin/sh

if [ "$1" == "commit" ]; then
   echo
   "${ARCH_ARCHIVE}/${ARCH_CATEGORY}--${ARCH_BRANCH}--${ARCH_VERSION}--${ARCH_REVISION}
   created" \
   | mail octopus@bluegate.org
fi

より複雑な例は以下である:

#!/bin/sh

case "$1" in
    precommit)
        ;;
    commit)
        ;;
    …
esac

レシピ集

すでに述べたように GNU arch には非常に原始的なたくさんのコマ ンドがある。これは Unix コマンドのようにパイプライン上などで組み合 わせて利用することを前提として作られたプリミティブがたくさんあるか らだ。これは融通が利く反面、利用しはじめた人にとってはどれとどれを どのように組み合わせれば作業が楽になるかがはっきりしない。実践的な ワークフローを作るにはノウハウがいる。ここではそのような「必殺技」 の数々をおめにかけよう。

私の過去を返して!

人生をやり直したい。残念ながらそんな深刻な君の悩みに対して 私は何もできないが、君のアーカイブバージョンについてならまかせて ほしい。いま、A/C--B--V--patch-10 をコミットした直後のプロジェク トツリーにいるとする。A/C--B--V--patch-8 に戻って、それをそのま ま A/C--B--V--patch-11 としてコミットしたい。ここでのポイントは tla replay コマンドの --reverse オプションで時間を逆向きに進むと いうものだが、パッチログも patch-8 の状態に戻ってしまう関係でそ のままではコミットできない。そこで最後に sync-tree を、お見舞い する。最初の undo はプリスティンからの変更があったときのことを考 えて一応バックアップしてみたということ。

$ tla undo
$ tla replay --reverse patch-10
$ tla replay --reverse patch-9
$ tla sync-tree patch-9
$ tla sync-tree patch-10
$ tla commit -L'hello my new world.'
$

チェンジセット patch-10 は、patch-9 と patch-10 をつなぐも のであることに注意。つまりチェンジセットの逆向きの適用は後のリビ ジョン名を指定すればうまくいく。

プロジェクトツリーにいながらにして分岐したい

今いる A/C--B--V--patch-5 のプロジェクトツリーの分岐を作っ てそちらで作業を続けたい。たとえば、ちょっとした実験的な機能を思 いついたから、分岐を作ってそっちで実験してみたいが、もともとの開 発ラインをその作業で汚したくない。普通ならこうやる:

$ tla -S tag A/C--B--V--patch-5 A1/C1--B1--V1
$ cd [これからサブディレクトリを作るどこかのディレクトリ]
$ tla get A1/C1--B1--V1
$

これだとそれまでいたプロジェクトツリーとは別のディレクトリ を用意してそちらに移る必要がある。こんなこと年中やるような処理で もないし、いいじゃないかという気もするのだが、君はそれすら面倒だ と言う。このようなものぐさこそ、フリーソフトウェアの輝かしい歴史 の原動力になるのだと君は理屈を言う。よろしい。私にまかせたまえ。 君はいまプロジェクトツリーにいることが前提になる。

$ tla -S tag A/C--B--V--patch-5 A1/C1--B1--V1
$ tla join-branch A1/C1--B1--V1
$ tla set-tree-version A1/C1--B1--V1
$

実はこれは私が思いついたものではない。Miles Bader のアーカ イブなどを参考にしてほしい。tla fork-tree のようなコマンドの実装 がある。

オフラインで分岐を作ってそちらにスイッチしたい

あるリモートアーカイブにあるバージョンの内容をちょっと見た くて tla get してみたが、後で本格的な分岐を作ってハックしたくなっ たとする。ところがネットワーク障害でリモートアーカイブがダウンし ていたり、いま自分がいる場所が電車の中でラップトップをいじってい るような状況で、そのアーカイブに接続できない。tla tag コマンドは リモートアーカイブにアクセスしにいこうとするので、一つ前の方法で はローカルマシンに分岐を作ることができない。さて困った。こんなと きには以下のようにすると、オフラインのまま分岐することができる。 tla rescue-tree とも呼ぶことのできる技だ。分岐先アーカイブバージョ ンを A/C--B--V とし、元アーカイブバージョンのプロジェクトツリー にいると仮定する。

$ tla undo
$ tla archive-setup A/C--B--V
$ tla set-tree-version A/C--B--V
$ tla add-log-version A/C--B--V
$ tla import
$ tla redo
$ tla commit -L'hehe, now switched. :)'
$

実はこうして作ったアーカイブバージョン A/C--B--V は base-0 リビジョンに継続情報を持たないので厳密に言えば本当の分岐ではない。 しかし保持しているパッチログは本物の分岐と等価なので、これ以降の 親バージョンからのマージについては update/replay/star-merge いず れも問題なく動作することを確認している。継続情報は実は分岐先のパッ チログの数を減らすための最適化に関係した仕組みでしかないのだ。

いまいるプロジェクトツリーの内容を tar ファイルに固めたい

tla inventory はプロジェクトツリー内部のディレクトリのトラ バースには欠かせない。君のプロジェクトを tar で固めてみよう。こ れには次のようにする。固めたファイルは一つ上のディレクトリにでき るようなサンプルにしてみた。

$ tla inventory -s | tar -T- -zcvf ../`tla tree-version`.tar.gz
$

いまいるプロジェクトツリーの中のソースファイルを grep し たい

tla inventory + xargs のような組み合わせもよく利用する。 unix の find(1) でも同じことができそうに思うが、{arch}サブディレ クトリ配下がノイズになってしまう。君のプロジェクト内にあるソース ファイル全体に対して grep してみよう。

$ tla inventory -s | xargs -l grep -H 'arch-tag'

tla inventory はソースファイルだけではなく、6っつのグルー プそれぞれを列挙するオプションがあるので、応用の仕方は明らかだろ う。たとえば、「プロジェクトツリー内のバックアップ属性ファイルを すべて消す」などなど。

第10章 マルチツリープロジェクト

複数のプロジェクトツリーを一緒にして、何かのプログラムを開発 したいということがある。たとえば汎用的なライブラリモジュールをひと つのアーカイブバージョンとして開発してあり、その上位にそのライブラ リを利用した別のプロジェクトを作りたいような場合、プロジェクトを二 つの構成要素に分離して、組み合わせることができると便利だろう。ライ ブラリモジュールは別のプロジェクトでも使いまわすことができるからだ。 このようなプロジェクトをマルチツリープロジェクトと言う。

幸いなことに、マルチツリープロジェクトには良い例がある。GNU arch 自身が hackerlab というライブラリ上に作られており、hackerlab は tla とは別のアーカイブバージョンとして独立に管理されているから だ。この章では GNU arch のソースコード自身を例としてマルチツリープ ロジェクトの説明をしていく。その後、マルチツリープロジェクトの分岐 を作る方法について説明する。これがわかれば君は GNU arch 自身をハッ クすることができるようになる。

概要

マルチツリープロジェクトはツリーの構成を記述しているだけの設 定用アーカイブバージョンと、その設定から読み込まれる要素となるアー カイブバージョンから構成される。設定用アーカイブバージョンには設定 ファイルがあり、どのアーカイブを、どのサブディレクトリに取り込むか を記述する。

GNU arch 本体の場合、アーカイブバージョン間の関係は以下のよ うになっている。

lord@emf.net--2004/dists--devo--1.0

設定用アーカイブバージョン。以下のバージョンの構成方法についての 記述がある。

lord@emf.net--2004/package-framework--devo--1.0

コンパイル/インストールするための汎用的なビルドシステム。

lord@emf.net--2004/tla--devo--1.3

GNU arch 本体。必要に応じて hackerlab ライブラリを呼び出す。

lord@emf.net--2004/hackerlab--devo--1.0

GNU arch 本体から呼び出されるライブラリ。pika など他のプロジェク トでも利用される汎用的なもの。

各構成バージョンのversion 名が、1.0 とか 1.3 とかまちまちに なっていることに注意しよう。何度か言ってきたように、GNU arch は異 なるバージョン間のバージョン名には、そのままでは何の関係もない。マ ルチツリープロジェクトを展開するには、設定用アーカイブバージョンを 通常の方法で tla get する。マルチツリープロジェクトの一部として利 用されるアーカイブバージョンと言えども、単独で見た場合には普通のバー ジョンとなんら変わることはなく、バージョンに対してできるすべての操 作が可能であることに注意しよう:

$ tla get -A lord@emf.net--2004 dists--devo--1.0--patch-10 dists--devo--1.0
* from archive cached: lord@emf.net--2004/dists--devo--1.0--base-0
* patching for revision: lord@emf.net--2004/dists--devo--1.0--patch-1
* patching for revision: lord@emf.net--2004/dists--devo--1.0--patch-2
* patching for revision: lord@emf.net--2004/dists--devo--1.0--patch-3
* patching for revision: lord@emf.net--2004/dists--devo--1.0--patch-4
* patching for revision: lord@emf.net--2004/dists--devo--1.0--patch-5
* patching for revision: lord@emf.net--2004/dists--devo--1.0--patch-6
* patching for revision: lord@emf.net--2004/dists--devo--1.0--patch-7
* patching for revision: lord@emf.net--2004/dists--devo--1.0--patch-8
* patching for revision: lord@emf.net--2004/dists--devo--1.0--patch-9
* patching for revision: lord@emf.net--2004/dists--devo--1.0--patch-10
* making pristine copy
* tree version set lord@emf.net--2004/dists--devo--1.0
$ cd dists--devo--1.0
$ ls
=ARCH-USERS-README  =INSTALL  =RELEASE-ID  COPYING  configs  {arch}
$

リビジョン番号は開発が進むにつれてもっと大きな番号になってい るかも知れない。設定用バージョンには、他のどのアーカイブバージョン をどのディレクトリに読み込むかについての定義ファイルがある。定義ファ イルはどのような名前にしても良いが、設定用バージョンのルートディレ クトリか、ルートディレクトリの下の ./configs ディレクトリ配下に置 かなくてはならないという決まりがある。定義ファイルは用途に応じた複 数個を用意することもでき、個数が多いようなら ./configs ディレクト リの下にまとめた方が整理しやすくなる。./configs ディレクトリの下に はサブディレクトリを作り、更に細かく定義ファイルを整理することもで きる。実際 GNU arch ではそのようにして ./configs/emf.net などのディ レクトリが作られている。

定義ファイルの内容は

ディレクトリ名   バージョン名

のような複数行からなる。空白だけの行、# で始まる行をコメント として利用することができる。GNU arch にある ./configs/emf.net/devo.tlaという定義ファイルは以下のようになってい る:

# Check out a tla arch distribution from the devo branches.  Latest
# revisions.
#

./src                   lord@emf.net--2004/package-framework--devo--1.0
./src/tla               lord@emf.net--2004/tla--devo--1.3
./src/hackerlab         lord@emf.net--2004/hackerlab--devo--1.0

./src/docs-tla          lord@emf.net--2004/docs-tla--devo--1.0
./src/docs-hackerlab    lord@emf.net--2004/docs-hackerlab--devo--1.0


# tag: Tom Lord Sat Jun 14 14:54:15 2003 (emf.net/devo.tla)
#

各行の意味は明らかだろう。./src というサブディレクトリの下に、 lord@emf.net--2004/package-framework--devo--1.0 というバージョンを 展開する、などの指定になる。実際の各バージョンの展開には tla build-config コマンドを使う:

$ tla build-config emf.net/devo.tla
…
$

余談だが、./configs ディレクトリにはこのほかにもさまざまな定義ファイル があり、Tom Lord が作った GNU arch 以外の公開されたソフトウェアは すべてこれらの定義ファイルから構築することができる。tla build-config が終了すれば、通常 tar ファイルとして配布される tla のソースコードが展開されていることがわかる。XXX 章に書いた方法を使 えばもちろんインストールできる。

GNU arch internal

せっかく GNU arch のソースコード本体について触れたので、ここ で GNU arch そのもののソースコードの編成について説明しようと思う。 ソースコードのディレクトリ構成はさまざまな理由で大きく変わる可能性 はある。ここでは tla-1.3 のツリー構成について説明する。興味のある 人はここでの説明を理解したら、次の節の方法で GNU arch の分岐を自分 のマシンに作っていつでもハックし始めることができる。

際上位ディレクトリは以下のような雰囲気になっている。

$ ls
=ARCH-USERS-README  =INSTALL  =RELEASE-ID  COPYING  configs  src  {arch}
$ 

ここはあまり見るべきものはない。configs の下にマルチツリープ ロジェクト構築に必要な情報があるだけでどうということはない。重要な のは src ディレクトリの下だ。降りてみる:

$ cd src
$ ls
COPYING      Maintfile	  PLUGIN       configure       docs-tla   links  {arch}
ChangeLog.d  Makefile.in  build-tools  docs-hackerlab  hackerlab  tla
$ 

すこし面白くなってくる。この階層は基本的には Tom Lord が自分 で作ったビルドシステムに関係している。./configure という名前のファ イルがあるが、これが実際に tla をコンパイルする時に走らせるシェル スクリプトだ。tla 本体をハックする場合に関係するディレクトリは hackerlab と tla だけだ。hackerlab は tla とは独立したライブラリ群 で、GNU の glibc のような感じのさまざまなルーチンが入っている。tla に降りてみる:

$ cd tla
$ ls
=THANKS		COPYING      Makefile.in  libawk      libneon  {arch}
=TODO		ChangeLog    PLUGIN	  libdate     tests
=gpg-check.awk	ChangeLog.d  libarch	  libfsutils  tla
$ 

だいぶ核心に近づいてきたが、まだごちゃごちゃしている。'='文 字で始まるファイルは、例によって深く考えなくても良い。この下の libarch。ここが tla の心臓になる:

$ cd libarch
$ ls
=scraps			 cmd-get-changeset.h	    cmd-sync-tree.h
Makefile.in		 cmd-get.c		    cmd-tag.c
PLUGIN			 cmd-get.h		    cmd-tag.h
ancestry.c		 cmd-grab.c		    cmd-tree-lint.c
ancestry.h		 cmd-grab.h		    cmd-tree-lint.h
apply-changeset.c	 cmd-help.c		    cmd-tree-root.c

…

cmd-file-find.c		 cmd-show-changeset.c	    undo.c
cmd-file-find.h		 cmd-show-changeset.h	    undo.h
cmd-find-pristine.c	 cmd-star-merge.c	    whats-new.c
cmd-find-pristine.h	 cmd-star-merge.h	    whats-new.h
cmd-get-changeset.c	 cmd-sync-tree.c
$ 

ここには非常にたくさんのソースファイルがそのまま並んでいる。 数が多いので詳細は省略した。大雑把に言うと、tla foo というコマンド に対応して、cmd-foo.c と cmd-foo.h という二つのソースファイルがほ ぼ必ず存在すると考えて良い。この cmd-foo.c に書ききれる程度の機能 でしかないコマンドの場合には cmd-foo.c のみで話が終る。一つのファ イルで記述するには規模が大きすぎたり、コマンド間で共通の機能として くくり出す場合には、他のファイルが関係していることもある。この場合、 cmd-foo.c の他に、foo.c のような名前になることが多い。たとえば少し 変則的だが、tla my-id に対応するソースコードは cmd-my-id.c であり、 他の my がつくコマンドとの共通部分のソースコードは my.c に存在する、 といった具合になる。cmd-my-id.c と my.c は、GNU arch のコマンドの、 スケルトンと言っても良いくらい単純なので、新しいコマンドを追加しよ うとする人は、まずはここから読み始めるのがおすすめだ。

各コマンドのディスパッチテーブルは cmds.c にある。cmd-xxx.c で作ったコマンドをここに登録すれば tla help などの一覧でも表示され るようになり、実際に呼び出すこともできるようになる。

以下、特に注目すべきファイルを挙げる

namespace.c

GNU arch で利用されるさまざまな名前がどのような形式であるかを決めるモ ジュール。ここを書き換えるとさまざまな名前の規則を変更すること ができる。ハックは容易だが名前空間の変更はアーカイブの互換性を 失わせる結果になることが多いので注意が必要である。

invent.c

ファイルの インベントリチェックや、グループ判別ロジックがある。あるファイ ルがどのグループに属し、ソースファイルである場合にはそのインベ ントリid は何であるかはここから inv-ids.c の関数を利用してで解 析される。

make-changeset.c

GNU diff のツリーへの拡張である mkpatch() 関数 のあるモジュール。

appply-changeset.c

GNU patch のツリーへの拡張である dopatch() 関 数のあるモジュール。make-changeset.c と合わせて、GNU arch の核 心をなしている。

star-merge.c

パッチ ログの履歴や、共通祖先などの状況を考慮した上で二つのツリーをで きる限り適切にマージする star merge の実装。tla の内部では最も 高いレイアにある部分。外部コマンドとして括り出しても良いくらい のモジュール。

archive-pfs.c

GNU arch のストーレージインターフェース用ファンクションディスパッ チテーブルのあるモジュール。

archive.h

GNU arch のアーカイブオペレーション用ファンクションディスパッチテーブル、 struct arch_archive_vtable の定義があるヘッダ。このディスパッ チテーブルの具体的な実装として現時点で存在しているのが pfs-dav.c, pfs-fs.c, pfs-ftp.c, pfs-sftp.c の四つで、それぞれ WebDAV、通常のファイルシステム、ftp、sftp の実装に対応している。

pfs.h

GNU arch のファ イルシステムオペレーション用ファンクションディスパッチテーブル、 struct arch_pfs_vtable の定義があるモジュール。GNU arch のストー レージインターフェースは arch_archive_vtable とこの arch_pfs_vtable の二つのテーブルで完全に抽象化されている。

カスタマイズの方法

第1節で tla build-config を使って tla のソースコードを展開し た。ここでは tla のソースコードに実際に手を入れる方法について説明 しよう。既にのべたように tla はひとつの設定用アーカイブバージョン と、四つの独立したアーカイブバージョンをまとめたものだった。tla を 修正する場合は、このうち、tla--devo--1.3 と hackerlab--devo--1.0 のどちらかに 対して修正を入れることがほとんどなので、これを前提としてカスタマイ ズの仕方を考えてみる。まず、直接 Tom Lord のアーカイブを修正するこ とはできないので、tla と hackerlab の分岐を、ローカルマシンに作る。 ここでは分岐先アーカイブバージョン名を、それぞれ tla--foo--1.3と hackerlab--foo--1.0としよう。

$ tla archive-setup tla--foo--1.3
…
$ tla archive-setup hackerlab--foo--1.0
…
$ tla archive-setup dists--devo--1.0
…
$

通常の分岐を作る操作と全く同じで、それぞれのバージョンに対し てtla tag を実行する。

$ tla tag lord@emf.net--2004/tla--devo--1.3 octopus@bluegate.org/tla--foo--1.3
…
$ tla tag lord@emf.net--2004/hackerlab--devo--1.0 octopus@bluegate.org/hackerlab--foo--1.0
…
$ tla tag lord@emf.net--2004/dists--devo--1.0 octopus@bluegate.org/dists--foo--1.0
…
$

dists--foo--1.0 を get する。当たり前だが dists--devo--1.0 とまったく同じものになる。

$ tla get dists--foo--1.0
…
$

独自の設定を作るため、./configs/emf.net/devo.tla をコピーす る。ここでは ./config/emf.net/foo.tla としよう

警告

foo.tla は devo.tla を単にコピーしただけなので、タ グラインの方法でインベントリidを付与されている devo.tla と、 foo.tla とのインベントリidが重複してしまう。これをさけるため、コピー 後、foo.tla のインベントリidを別のものに変更する必要がある。

./config/emf.net/foo.tla を編集し、以下のように tla と hackerlab を分岐後のものとする:

# Check out a tla arch distribution from the devo branches.  Latest
# revisions.
#

./src                   lord@emf.net--2004/package-framework--devo--1.0
./src/tla               octopus@bluegate.org--2004/tla--foo--1.3
./src/hackerlab         foo@bleugate.org--2004/hackerlab--foo--1.0

./src/docs-tla          lord@emf.net--2004/docs-tla--devo--1.0
./src/docs-hackerlab    lord@emf.net--2004/docs-hackerlab--devo--1.0


# tag: Tom Lord Sat Jun 14 14:54:15 2003 (emf.net/devo.tla)
#

あとは、tla build-config をいま作った定義ファイルによって構 築すればよい:

$ tla build-config emf.net/foo.tla
…
$

これからの修正は、tla の部分については ./src/tla、hackerlab の部分については ./src/hackerlab に降りていって行えばよい。コミッ トは個別のアーカイブバージョンのディレクトリで行なえばよい。繰り返 すが、後は異なる 3っつのアーカイブバージョンのプロジェクトツリーが たまたま特別なディレクトリの上下関係の中に展開されているだけだ。

付録 A. 名前規約と各種ファイル形式

この補遺では GNU arch で利用されるさまざまな名前で利用できる 文字についての詳細と、ファイル形式についての詳細を説明する。

名前規約

GNU arch ではいろいろな名前が利用される。それぞれの名前には 名前規約を持つものが多い。名前規約は主に正規表現で定義されるが、そ れだけとは限らない。以下ではそれぞれの名前の定義と、その名前規約に ついてひとつづつ説明する。

User ID と UID

User ID は、tla my-id コマンドで設定される tla 利用者を区 別するための識別子である。User ID はさらにその部分文字列として UIDを含む。これは直観的に言うと E-mail アドレスのような形の文字 列を許す。

User ID の厳密な定義は正規表現で[ほぼ]以下のものである

^[a-zA-Z0-9 \t]*<[-+_.a-zA-Z0-9]+@[-_.a-zA-Z0-9]+>$

UID の厳密な定義は正規表現で[ほぼ]以下のものである

^[-+_.a-zA-Z0-9]+@[-_.a-zA-Z0-9]+$

アーカイブ名

アーカイブ名は[ほぼ]以下の正規表現で表されるものである

xxx@yyy.zzz
or
xxx@yyy.zzz--www

ただし xxx などは、^[-a-zA-Z0-9]+$ かつ、'-' 文字が連続し ないような文字列

カテゴリ名とブランチ名

カテゴリ名とブランチ名はいずれも[ほぼ]以下の正規表現であらわされ るものである

^[a-zA-Z][-a-zA-Z0-9]*$

ただし、'-' 文字が連続しないような文字列

バージョン名

バージョン名は[ほぼ]以下の正規表現であらわされるものである

^[0-9]+(\.[0-9]+)*$

パッチレベル名

パッチレベル名は[ほぼ]以下の正規表現であらわされるものである

^(base|patch|version|versionfix)-[0-9]+$

ただし、base の場合には base-0 のみが許される。

各種ファイル形式

GNU arch はファイルシステム中にさまざまな形式のファイル、ディ レクトリを作る。ここでは GNU arch が作るこれらのアイテムの編成や形 式について説明する。

チェンジセット

GNU arch の根幹を支えるデータ構造がチェンジセットであるこ とは繰り返し述べてきた。新しいリビジョンを作るときに GNU arch 内 部で処理されていることは、直前のリビジョンと今回のリビジョンの間 差分をチェンジセットとして求めることだ。求まったチェンジセットを tar で固めてアーカイブに追加すればコミットは完了する。チェンジセッ トは決まった形式のディレクトリとして表現される。以下がその構造だ。

インベントリマップ

チェンジセットの最上位ディレクトリ内には、ファイルとイン ベントリidの対応表がある。変更前ツリー/変更後ツリーの区別、ファ イル/ディレクトリの区別の組み合わせで四つのファイルがある。各 ファイル内はタブで区切られた二つのフィールドからなる。最初がファ イル名(ディレクトリ名)、次が対応するインベントリidである。いず れも sort -k 2 コマンドでソートされていると仮定してよい。

orig-dirs-index

変更前ツリー に存在しているすべてのサブディレクトリとそのインベントリid の対応表

mod-dirs-index

変更後ツリーに 存在しているすべてのサブディレクトリとそのインベントリidの 対応表

orig-files-index

変更前ツリー に存在していたすべての通常ファイルとそのインベントリidの対 応表

mod-files-index

変更後ツリー に存在しているすべての通常ファイルとそのインベントリidの対 応表

テーブル中の「通常ファイル」とは「ディレクトリ以外のファ イル」という意味である。つまりシンボリックリンクなども含む。

ディレクトリメタデータ

削除されたディレクトリ、追加されたディレクトリのファイル パーミッションなどを保存するために二つのファイルがある。通常の ファイルについては「ファイルの内容」を保存しなくてはならないの で、そのファイルのパーミッションで表現できるが、ディレクトリは 「ファイルの中身」が存在しないので、ファイルと同じ形式で持つの は無駄だ。そこで変更前、変更後用の二つのファイルに一覧を記録し てある。一行は、[メタデータ]タブ[名前]の形になる。

original-only-dir-metadata

変 更元のみに存在していたディレクトリのパーミッションの一覧

modified-only-dir-metadata

変 更後のみに存在していたディレクトリのパーミッションの一覧

両方のファイルとも、sort -t '<tab>' -k 2 でソートされて いることを仮定してよい。この二つのファイルに記録されるメタデー タは今後の拡張で追加される可能性がある。

削除ファイル、追加ファイル

ディレクトリ以外のファイルで削除されたもの、追加されたも のは、そのままの形で以下の二つのディレクトリに保存される。ファ イルの元ツリー中での相対的なパスは保存される。たとえば、. /foo/bar/baz.txt というファイルが削除された場合には、

./removed-files-archive/foo/bar/baz.txt

という名前のファイルにそっくりそのまま内容が保存される。 保存ファイルのパーミッションも厳密に保存される。

removed-files-archive

変更前ツ リーにのみ存在した全通常ファイルを格納するディレクトリ

new-files-archive

変更後ツリー にのみ存在する全通常ファイルを格納するディレクトリ

パッチファイル

最後に、patches ディレクトについて説明する。チェンジセッ ト最上位にあるこのディレクトリには変更前と変更後の差分に対応し たパッチファイルが保存されている。ファイルの追加や削除がなけれ ば、このディレクトリ内のパッチの情報が最も重要な情報になる。

それぞれのパッチは通常の GNUdiff の unidiff 形式のファイ ルだが、ファイルの内容に対する変更と同時にファイル名称変更があっ た場合には、変換前、変換後のファイル名称は異なる。patches ディ レクトリ配下のすべてのファイルは、常に変換後のファイ ル名を基準にして格納されるという決まりがある。

よく考えると、これは少し奇妙なことだ。なぜなら GNU arch のチェンジセットは可逆な性質があり、変更前、変更後の情報に対し て論理的には完全に同等の関係にあるからだ。しかし実際の表現方法 を見ると、このようにパリティーが変換後に傾いている。これはなぜ だろうか? おそらく実際の利用でのチェンジセットの適用は変換前か ら変換後の方法に向かうことがほとんどであり、このような構成にし ておいたほうが処理が効率化されるのだろう。

patches ディレクトリにある具体的なファイルは以下のような ものである。ただし new_name は今いったように変換後の名前である。 new_name がサブディレクトリにあれば、patches 配下も対応したサ ブディレクトリができるのは remove-files-archive などのディレク トリと同じである。

new_name.link-orig

変更前のシンボリックリンク名を含む

new_name.link-mod

変更後のシンボリックリンク名を含む

new_name.original

変更前のファイル内容をそのまま含む

new_name.modified

変更後のファイル内容をそのまま含む

new_name.patch

変更前・後のファイルの差分を unified 形式で 持つ

new_name.meta-orig

変更前のメタ・データを含む

new_name.meta-mod

変更後のメタ・データを含む

new_name/=dir-meta-orig

変更前のディレクトリ・メタ・データを含む

new_name/=dir-meta-mod

変更後のディレクトリ・メタ・データを含む

チェンジセットの計算はリビジョン間だけではなく、任意のツリー 間に対して行うことができる。リビジョン間のチェンジセットは {arch}サブディレクトリを管理領域として必ず含んでいることに特徴が ある。

チェンジセットに関係してふたつの演算がある。チェンジセット を求める演算と、適用する演算だ。それぞれ tla changeset, tla apply-changeset コマンドに対応する。前者は任意のツリー間に対して 必ず値が求まり成功するが、後者は失敗することもある。これは任意の 数の2乗は必ず計算できるが、その逆の演算である平方根が常にもとま るとは限らないのと似ている。

{arch}管理領域

プロジェクトツリーのルートディレクトリにある{arch}管理領域 直下には以下のようなファイルがある

表 A.1. ファイル一覧

ファイル名F/D説明
++default-versionFtla set-tree-version で設定されるデフォルトバージョ ン名が、A/C--B--V の形で記録されている。
++pristine-treesDプロジェクトツリーに追加されたプリスティンツリー が保存される。このディレクトリに下に更に locked/ と unlocked/ というサブディレクトリが作られ、そこに格納され る。詳しくは tla lock-pristine コマンドを参照のこと。
,,inode-sigsDインベントリスキャンを高速化するためのi-nodeキャッシュ 情報があるディレクトリ。高速化にのみ関係しているので、',,' で始まる名称に従い junk ファイルとみなせる。つまり、常に (そのような場面はほとんどありえないが、とにかく)ディレク トリごと安全に消すことができる。ディレクトリの下には A%C--B--V--R という名前のサブディレクトリがあり、その中 にリビジョンごとのi-nodeキャッシュ情報がある。
.arch-project-treeFこのプロジェクトツリーのバージョン情報が入った通 常ファイル。プロジェクトツリーの形式が今後大きく変わった 場合にはこのファイル内容が区別できるような別の文字列にな ると考えられる。
=tagging-methodFインベントリタグの大域的なタグづ け方法を決めたり、GNU arch が認識する 6種類のファイルタ イプを定義するためのファイル。実際の利用において、{arch} 管理領域中、唯一手で編集されることのあるファイルである。
上記以外のディレクトリDパッチログのためのディレクトリに なる。カテゴリ名として存在する。

上記で、プリスティンツリーの構造は、 ./C/C--B/C--B--V/A/C--B--V--R/ のような構成になる。この最後のサ ブディレクトリの下にプロジェクトツリーのルートにあるツリーと全く 同じ形式のツリーが保存される形になる。ただしプリスティンツリーの プリスティンツリーは存在しない。階層のループが発生してしまうので 自明であろう。

パッチログの構造は、./C/C--B/C--B--V/A/patch-log/R という 形になる。最後の R はリビジョン名をもつ通常ファイルである。

アーカイブ領域

アーカイブ領域は import/commit コマンドなどにより新しくで きたリビジョンの差分情報を格納する場所である。いったん格納された データは永続的に保存され、以後修正が加わることはない。この意味で アーカイブは基本的にはサイズが増加する一方だと言える。例外はリビ ジョンキャッシュ情報で、tla uncacherev コマンドを実行するとアー カイブ中のキャッシュは削除される。もちろんこれはキャッシュの削除 なのでアーカイブの論理的な情報量が減るわけではない。アーカイブは 複数のバージョンから構成され、アーカイブ + バージョン一つの論 理的なバージョン管理単位となり、他のバージョン管理システムで「リ ポジトリ」と呼ばれる単位にほぼ相当する。

表 A.2. ファイル一覧

ファイル名F/D説明
=meta-infoDアーカイブ全体についてのメタ情報が格納されるディ レクトリ。現時点では name, mirror, signed-archive の三つ ファイルが存在しうる。name はこのアーカイブの名前、 mirror はこのアーカイブのミラーとしての名前、 signed-archive はこのアーカイブがサインつきであることを 示すファイルである。
.archive-versionFアーカイブの形式を示すバージョン情報文字列を含む ファイルである。今後の拡張でアーカイブの形式が大きく変わ るような場合にはこの中の文字列が変更になると考えられる。
上記以外のディレクトリDそれぞれカテゴリを示すディレクト リ。この下に実際のアーカイブバージョンが格納される。

アーカイブの際上位ディレクトリの名前は、実際に結びつけられ るアーカイブ名と一致させる必要はなく、任意の名前で作成してよい。 アーカイブ名との関連は =meta-info/name ファイルによって知ること ができるためである。しかし、特に理由がない限りアーカイブ名に一致 したものとすることを勧める。これには tla make-archive コマンドで アーカイブ位置を示すディレクトリの最後の部分をアーカイブ名に一致 させればよい。たとえば:

$ tla make-archive octopus@bluegate.org--2004 \
      /home/octopus/{archives}/octopus@bluegate.org--2004

のようにする。この規則を明示的に破る必要がある場面もある。 詳しくはアーカイブミラーなどの章を参照してほしい。

上記の表での実際の個別のバージョンが含まれるサブディレクト リについてさらに詳しく説明する。サブディレクトリは、 ./C/C--B/C--B--V/R の形をしている。最後の R はリビジョン名でディ レクトリである。このディレクトリ中にはリビジョンのタイプに応じて 各種のファイルが格納される。リビジョンのタイプは、初期リビジョン[i]、 チェンジセットリビジョン[x]、継続リビジョン[c]の三つがある。初期 リビジョンとは import コマンドで新規に作成されたリビジョンで、チェ ンジセットではなく初期ツリー全体が格納されている。通常は継続コマ ンド以外の base-0 リビジョンがこれにあたる。チェンジセットリビジョ ンは通常のコミットで作成されたリビジョンで、直前のリビジョンから の差分情報のみをもつ。patcn-n の形のリビジョンは普通この形になる。 継続リビジョンは tla tag コマンドによって作られた継続情報を持つ ような特殊なリビジョンである。

表 A.3. ファイル一覧

ファイル名i/x/c説明
C--B--V--R.tar.gzicx基本的には初期リビジョンのみで 存在する、初期ツリーの状態そのものを tar で固めたファイ ル。このファイルを展開すれば初期リビジョンがそのまま取得 できる。tla cacherev コマンドでリビジョンをキャッシュし た場合にはチェンジセットリビジョンでも存在する。
C--B--V--R.patches.tar.gz_xcチェンジセットリビジョンでは直前のリビジョンから の差分を示すチェンジセット(これはディレクトリであること を思い出してほしい)を tar で固めたファイル。継続リビジョ ンの場合にも継続を示すチェンジセットが格納されるが、これ はほとんど空で、継続を意味するパッチログのみを含む特殊な チェンジセットになる。
CONTINUATION__c継続リビジョンでだけ存在する。 継続元のリビジョンが A/C--B--V--R の形式で保存されたファ イル。
checksum???このリビジョンの本来の内容を示 す *.tar.gz ファイルに対して計算 されたチェックサムの値が入ったファイル。サインつきアーカ イブの場合にはさらにこの結果にサインが施されている。
checksum.cacherev???このリビジョンが tla cacherev によってリビジョンキャッシュを含む場合、そのキャッシュ用 の *.tar.gz ファイルに対して計算されたチェックサムの値が 入ったファイル。サインつきアーカイブの場合にはさらにこの 結果にサインが施されている。
log???このリビジョンのパッチログ。こ のファイルは *.tar.gz ファイル中にまったく同一のものが存 在するが、簡単に参照できるようにするため単独ファイルの形 で重複して存在している。これを見れば *.tar.gz を展開して その中のファイルをわざわざ取り出さなくてもこのリビジョン でどのような修正があったかを大まかに知ることができる。
++revision-lock???バージョン中の最新リビジョンディ レクトリに存在する。リビジョンがこのバージョンに追加され る際に排他制御を正しく行なうために存在するディレクトリ。 トランザクション実行中以外は、このディレクトリには +contents という名前の、ファイルを一つも含まない唯一のサ ブディレクトリが存在する。リビジョン追加のトランザクショ ンについては XXX を参照してほしい。

ライブラリ領域

ライブラリ領域は、実際に tla get されたリビジョンのプロジェ クトツリーがそのまま集められた巨大な領域である。同じバージョン中 のリビジョン同士では変更が加えられていないファイルも多いので、そ のようなものについてはハードリンクの手法を利用することで空間を節 約している。

表 A.4. ファイル一覧

ファイル名F/D説明
=sparseFライブラリを sparse 属性にする かどうかを決めるフラグとしてのファイル。ファイル内容は空 である。このファイルが存在すると、ライブラリは sparse とさ れる。sparse とは、あるリビジョンをライブラリに追加する ときに副産物として計算することのできる別のリビジョンを同 時に自動的に追加するかどうかを決めるもので、sparse を指 定するとこの自動追加機能が働かない。結果としてライブラリ 領域のサイズは小さくなる。
=greedyFライブラリを greedy 属性にするかどうかを決めるフ ラグとしてのファイル。ファイル内容は空である。このファイ ルが存在すると、ライブラリは暗黙に計算されるリビジョンを ライブラリに登録する。たとえば tla get コマンドであるリ ビジョンのプロジェクトツリーをどこかに構築した場合、この プロジェクトツリーを特に指定しなくてもライブラリに追加す る。これはライブラリコマンドを実行しなくても自然とtlaシ ステムが高速化されることにつながる。
その他のファイルDアーカイブ名をもつディレクトリに なる。このディレクトリ名を A とすると、 ./A/C/C--B/C--B--V/C--B--V--R というディレクトリができて、 最下位のディレクトリ中に、リビジョン A/C--B--V--R のプロ ジェクトツリーの内容が実際に展開される。

./A/C/C--B/C--B--V/C--B--V--R 配下のプロジェクトツリーには 通常展開されるプロジェクトツリーの内容に加えて以下のファイル/ディ レクトリが存在する。

表 A.5. ファイル一覧

ファイル名F/D説明
,,indexFプロジェクトツリー中のファイルと ファイルに対応したインベントリid とのペアのリスト。
,,index-by-nameF,,index と本質的に同じ内容だが、ファイル名でソー トされている。
,,patch-setDこのリビジョン名をもつチェンジセッ トが保存されているディレクトリ。通常のチェンジセットのほ かに、=ancestor, =previous, =log.txt の三つの追加情報も 保存されていて、パッチログメッセージやこのリビジョンの前 のリビジョンなどの関係を把握することができるようになって いる。

.arch-params

各種一時ファイル

ここでは GNU arch 内部で利用されるさまざまなファイルをでき る限り網羅して説明する。これらのファイルは内部的に利用されるだけ で通常利用者が直接考慮する必要はないものだが、ハックの際には必要 だろう。列挙したファイルがすべてではないし、GNU arch の細かいバー ジョンによって増減や名称変更があると思う。この点についてはご了承 願いたい。

UUID(GUID)

GNU arch では、「誰とも重複しないような名前」や、「誰とも重 複しないような数」を必要とする場面がよくある。たとえば、君がこれか ら作るアーカイブ名は、地球上の別の誰とも異なっていなくてはならない。 このために君の E-mail アドレスをアーカイブの一部として利用するとい う決まりがあるのだった。いま、わざわざ君の E-mail アドレスを自分の アーカイブとするような意地悪な人間がとりあえず地球上にいないとすれ ば、これで君のアーカイブは地球上の誰とも衝突することはない。GNU arch は他にもこういう場面がある。インベントリid を決める時だ。イン ベントリid も、他のどんなアーカイブのどんなインベントリidとも異なっ ていなくてはならない。ある特定のバージョンや、アーカイブ中で一意で あれば済む問題ではない。地球上のすべてのアーカイブ中のすべてのイン ベントリidと衝突してはいけない。衝突したからと言って破滅的なことが 起こることはないが、やはり奇妙なエラーが出るはずだ。tla id-tagging-method で names の方式が好まれないのはこのためだ。この 方法だと、たとえば ?./README.txt のようなインベントリidが生成され てしまい、これは簡単に他のアーカイブバージョンのまったく無関係な ?./README.txt と衝突してしまうのだ[17]

どうしたらいいだろう。そうだ、世界中の GNU arch ユーザがみん なでどこかに集まって番号を取り決めればよいかも知れない。「文字列発 行専用メーリングリスト」を作って、たとえば、私が議長になって、新し い文字列が欲しいときには私にメールすること、とか言う決まりを作れば いい。で、私は 000000000000000000001 番から順番に、メールしてきた 人順に +1 した文字列を払い出せばいい。これで原理的に決して衝突しな い文字列を事実上無限に作り出すことができる。これは良いアイディアだ ろうか? とんでもない。最悪のしくみだ。なぜだろう?

まず第一に、私はこんな単純な作業をやりたくはない。

プレシャス、バックアップ、ジャンクの具体的な意味

プレシャス属性

GNU arch のファイルグループの一つに「プレシャス」がある。こ れはローカルにコピーされる場合にソースと共にコピーされるという性質 を与えられたものだが、「ローカルにコピーする」とは一体正確にはどの ような状況を指すのかを議論する。

プレシャスのコピーに関係したソースファイルは、

./src/tla/libarch/copy-project-tree.c

にある

arch_copy_project_tree()

関数であり、これが呼び出されるのは、以下の四つの場所である。

cmd-apply-delta.c:        arch_copy_project_tree (upon, dest, 1, 1);
cmd-join-branch.c:        arch_copy_project_tree (upon, dest, 1, 1);
cmd-sync-tree.c:        arch_copy_project_tree (upon_root, dest, 1, 1);
cmd-update.c:        arch_copy_project_tree (upon_root, dest, 1, 1);

つまり、これらのコマンドでは既存のプロジェクトツリー上で処理 を実行するかわりに --dest オプションで新規ディレクトリを指定して実 行することもできるが、この場合元になるプロジェクトツリー中のソース とプレシャスがそこにコピーされた後、それぞれのコマンドが実行される。

バックアップ属性とジャンク属性

バックアップとジャンクの属性の違いは、ジャンク属性が「安全 に削除できる」ということで示されている。が、現時点(tla-1.2) のソー スコードを見てもバックアップとジャンクのどちらかが特別に扱われて いる気配はない。これについて説明する。

現時点ではこの両者にははっきりした区別はない。ただし tla は内部的に ,, で始まるファイルを一時的なファイルとして利用してお り、これは =tagging-method などの設定がどうであれ必ず junk と見 なされる約束がある。このため、上記の意味にしたがって junk 属性を =tagging-method の中で適切に設定すれば、今後将来にわたっても

$ tla inventory -j | xargs rm -r

として、tla を内部的な一時ファイルを含むジャンクファイルす べてを削除することができる。そのような利用方法を狙っている。

トランザクション

以下は、archive-pfs.c のコメントからの抜粋である。

あるバージョン内にはリビジョンが一列になって並んでいる。新し いリビジョンはどれも順序づけされて、不分割で、独立し、永続的なもの として作成される必要がある。ファイルシステムアーカイブ中で、バージョ ンはディレクトリの形に実装され、リビジョンはその中にパッチレベル名 を持ったサブディレクトリとして実装される。(base-0, patch-1 ... な ど)。通常の rename システムコールはこのための仕組みをほぼ用意して くれる: tla クライアントは,,wants-to-be-patch-1-txnidのような名前 のディレクトリを作り、必要なリビジョンデータをそこに入れ、それから patch-1 のような名前に rename すれば良いように思える。クライアント はpatch-(N-1)が存在しない場合には patch-N を作らないものと取り決め ておけば、patch-Nのコミットに成功した別のクライアントがある場合に は rename を失敗するので、排他制御は正しく働くことになるように思え る。

しかしここに罠がある。base-0 あるいは patch-N の後の名前は固 定されたものではないのだ。patch-(N+1)かも知れないが、version-0 に なることもある。patch-N (あるいは base-0 )の後続リビジョンとして、 同時に patch-(N+1)と version-0 を作ろうとするクライアントがあった 場合には悲惨なことになる。rename はこの問題を直接解くことはないの だ。(さらに、"継続する形のロック"もサポートしたい。実際にコミット する前に新しいリビジョンをロックしておくことで、そのリビジョンに対 して別の誰かがコミットすることをあらかじめ防ぐようにしたい。)

で、かわりに以下のような仕組みを実装する。

あるバージョンのサブツリーは常に、唯一の(ネストしない) "リビ ジョンロック用ディレクトリ" を持つものとする。このディレクトリは常 に +contents と呼ばれるサブディレクトリを持つ。通常、+contents ディ レクトリは最終的には新しいリビジョン用のディレクトリとして rename されるものだ。

一般的に、リビジョンロックディレクトリの名前はロックの状態を 示す。書き込みトランザクションがロックを取得するときには +contents ディレクトリ中に新しいリビジョン用のデータ(これはネストされた新し いリビジョンロックディレクトリがあるが)を入れ、それから +contents をpatch-N(あるいは version-0、base-0、versionfix-N の名前)に rename し、後始末をする。

とりうるリビジョンロックの状態は以下である。

[A,B,C,D,E]

特殊なリビジョンと状態遷移

GNU arch で通常利用されるリビジョンは base-0 か patcn-n とい う形のものだ。ここで n は 1 以上の整数。しかしこのほかにも version-0 と versionfix-n という形のリビジョンが存在する。この二つ のリビジョンは tla commit コマンドで --seal と --fix オプションを 使うと生成される。これらの関係を状態遷移の形で示すと以下のようにな る。

図 A.1. コミットのオプションと状態遷移

コミットのオプションと状態遷移

これらの特殊リビジョンを過去の遺物と考え、利用を勧めない人も 多い。私もその一人である。が、疑問を一つでも抱えると先に進むことの できないタイプの人間も多い[18]。そして私はこちらにも属する。そんなわけで説明し た。「それはあなたには関係ないから気にしなくていい」こういう説明は、 私は嫌いだ。歴史家や考古学者にとって、自分に関係ないことなど一つも ないのだから。

繰り返しになるが、個人的にはこれらの特殊なリビジョンの利用に は反対である。また、特殊リビジョンをこれ以外にも定義して、それを利 用した形で tla を拡張することにも反対である。われわれの生きる世界 はもう十分複雑だ。さらに複雑にする理由は何もない。過去を繰り返す必 要はない。理解するだけにしよう。



[17] 繰り返すが、この ようなことがおきても致命的な話しにはならない。ただ GNU arch のすば らしい世界の一部が堪能できなくなることだけは確かだ。

[18] 小学生のとき、引いた数が どこに行ってしまうのかがわからなくて、大学で数学基礎論を学ぶまで、 私は引き算が理解できなかった。そのことは誰にも言わないでほしい。

付録 B. GNU arch関連情報

この補遺では GNU arch に関連したサードパーティー製ツールや、 リンク集などについて説明する。

ツール

リンク集

文句なしに一番重要なのは以下の場所だ

http://wiki.gnuarch.org

残念ながら英語だが、GNU arch に関するまとまった情報がある。 wikiでできているので、誰でも貢献することができる。率直に言って GNU arch はまだまだドキュメントが不足している。私がこのドキュメントを 書いているのもそれが理由だ。

上記の wiki からたどることができるが、

http://wiki.gnuarch.org/moin.cgi/Archive_20Registry

にはよく知られた有名なアーカイブの一覧がある。もちろんこのド キュメントの中で説明した方法で tla register して get / tag するこ とができる。

メーリングリストは、

http://mail.gnu.org/mailman/listinfo/gnu-arch-users

で、ここが GNU arch 公式のメーリングリストだ。users という名 前だが、利用者から開発者や貢献者まで入り混じっている。特に開発者用 のリストは現時点では存在しない。このドキュメントを読んでも理解でき ない部分についてはぜひこのリストに質問を投げてほしい。君が質問して くれれば、この本の精度はそれだけ高くなる。これは立派な貢献のやり方 の一つだ。

もし君が日本人なら、日本語のメーリングリストがある。これは私 が自分のサーバに作って私が管理している非公式のリストだ。現時点では あまり流量は多くないが、ある程度の質問には答えられると思う。

http://arch.bluegate.org/mailman/listinfo/arch-jp

付録 C. GNU arch コマンドリファレンス

目次

リファレンスの見方
tla サブコマンド
ヘルプコマンド
ユーザコマンド
tla my-id
プロジェクトツリーコマンド
tla init-tree
tla tree-root
tla tree-version
tla set-tree-version
tla undo
tla redo
tla changes
tla file-diffs
プロジェクトツリーインベントリコマンド
tla inventory
tla tree-lint
tla id
tla id-tagging-method
tla add-id
tla delete-id
tla move-id
tla mv
tla explicit-default
tla id-tagging-defaults
パッチセットコマンド
tla changeset
tla apply-changeset
tla show-changeset
アーカイブトランザクションコマンド
tla make-archive
tla archive-setup
tla make-category
tla make-branch
tla make-version
tla import
tla commit
tla get
tla get-changeset
tla lock-revision
tla archive-mirror
アーカイブコマンド
tla abrowse
tla rbrowse
tla categories
tla branches
tla versions
tla revisions
tla ancestry
tla ancestry-graph
tla cat-archive-log
tla cacherev
tla cachedrevs
tla uncacherev
tla archive-meta-info
tla archive-snapshot
tla archive-version
tla archive-fixup
パッチログコマンド
tla make-log
tla log-versions
tla add-log-version
tla remove-log-version
tla logs
tla cat-log
tla changelog
tla log-for-merge
tla merges
tla new-merges
マルチプロジェクト設定用コマンド
tla build-config
tla cat-config
ブランチとマージに関するコマンド
tla tag
tla update
tla replay
tla star-merge
tla apply-delta
tla missing
tla join-branch
tla sync-tree
tla delta
ローカルキャッシュ関連コマンド
tla changes
tla file-diffs
tla file-find
tla pristines
tla lock-pristine
tla add-pristine
tla find-pristine
リビジョンライブラリコマンド
tla my-revision-library
tla library-config
tla library-find
tla library-add
tla library-remove
tla library-archives
tla library-categories
tla library-branches
tla library-versions
tla library-revisions
tla library-log
tla library-file
公開用リビジョンコマンド
tla grab
スクリプト支援コマンド
tla parse-package-name
tla valid-package-name

この補遺は GNU arch のコマンドリファレンスです。ある程度内容 が充実するようなら、独立した本にしたほうが良いかも知れませんが、と りあえず補遺の形で始めてみます。

リファレンスの見方

このリファレンスでは(XXX)。変更の項目では、そのコマンドがど のデータに対して書き込む可能性があるかを示しました。これは四つのシ ンボル、[AWCL]からなります。A はアーカイブ領域、W はプロジェクトツ リー、C は設定領域(~/.arch-params)、L はライブラリ領域、をそれぞれ あらわします。ライブラリ領域の書き込みについてはさまざまな処理の途 中で暗黙に書き込みが起こる場合もあり、この記法では厳密には記述しき れていないものもあります。[----]となっているコマンドはどの領域にた いしてもせいぜいリードアクセスするだけなので気軽に試してみることが できます。

オプションの項では、どのコマンドでも必ず利用できる以下の三つ のオプションは省略しているので注意してください。

-h, --help     短い形式のヘルプを表示して終了します。
-H             長い形式のヘルプを表示して終了します。
-V, --version  リリース文字列を表示して終了します。

各コマンドに対する引数や説明中で、アーカイブ名、カテゴリ名、 ブランチ名、バージョン名、リビジョン名、そしてそれらの組み合わせに ついて語る場合、それぞれの名前部分を、A, C, B, V, R の一文字で表す 場合があります。たとえば A/C--B--V と書いた場合には、

octopus@bluegate.org--2004/hello--proj--1.0

のような文字列を思い浮かべてください。また、C--B と書いた場 合には同様に

hello--proj

のような文字列を想像してください。GNU arch では名前空間が複 雑で、さらに名前の構成部分とその構成結果の呼称があまり厳密に定義さ れていないので、このようにシンボリックに書き表すことで議論の対象を はっきりさせることにします。

tla サブコマンド

ヘルプコマンド

ユーザコマンド

この節ではすべてのユーザコマンドについて説明します。それぞ れのコマンドは、アーカイブ(CVSで言うリポジトリ)、プロジェクトツ リー(CVSで言う作業コピー)、そして設定管理領域(~/.arch-param)に対 して読み書きすることがあります。これらの領域に対してアクセスが発 生しないか、読み込みアクセスしか発生しない場合には '-'、書き込み が発生する場合 'w' でこの順に示すことにします。たとえば 'w--' と 書けば、アーカイブに対する書き込みは発生しますが、プロジェクトツ リー、設定管理領域に対する読み書きは発生しません。

名前

tla my-id — ユーザ id の表示と設定

用法

tla my-id [identify string]

説明

ユーザ ID は arch を利用する際にさまざまなアーカイブ とログメッセージ中に記録される識別子です。一行からなる印字可 能な文字からのみ構成されていなくてはなりません。以下の例のよ うなemailアドレスの形をしていなくてはならないという決まりが あります。

        Jane Hacker <jane.hacker@gnu.org>

<と>の間の部分の文字列は uid と言います。archは uid を使ってユニークなファイル名を生成することがあります。具 体的には XXX と XXX です。id の厳密な定義は正規表現で書くと XXXです。id の後に引数がある場合、その内容が ~/.arch-params/=id というファイルに保存されます。idをコマン ドラインから設定する場合には < や > のような文字がシェ ルの特殊文字と衝突してしまうので、ダブルクオート文字などでエ スケープして指定してください。

-u (--uid)オプションを利用すると id 文字列の uid の部 分だけが表示されます。-e (--errname)オプションを指定すると id の表示に失敗した場合にこのプログラムが呼び出されます。あ る人たちはemailアドレスのような情報がシステムのいたるところ に公開されてしまうのを嫌います。-e オプションは UUID 生成プ ログラムなどのような email アドレスには基づかない名前をかわ りに利用することを狙ったものです。

このコマンドは、GNU arch のインストール後に必ず実行し なくてはならないものの一つです。一度設定してしまえばそれ以上 利用することは少ないコマンドですが、このコマンドでなんらかの id を設定しないうちは GNU arch の多くのコマンドが利用できま せん。

別名

なし

変更: [--C-]

スイッチ

--errname (-e)
--uid (-u)

以下では、my-id の初期設定後、設定内容を確認しています。 Unix コマンドラインから id を入力する場合、'<'、'>'、 その他の特殊文字を扱うため、二重引用符でくくって指定している ことに注意してください。

$ tla my-id
arch: no arch user id set
$ tla my-id "Tez Kamihira <tez@kamihira.com>"
$ tla my-id
Tez Kamihira <tez@kamihira.com>

CVS対応コマンド

なし

プロジェクトツリーコマンド

GNU arch は他のオーソドックスなバージョン管理システムと同 様に、二つのデータが主な役割を演じます。ひとつはアーカイブ、もう ひとつは作業コピーです。アーカイブは、CVS で言うリポジトリのこと です。作業コピーは GNU arch の世界ではプロジェクトツリーと呼ばれ ます。アーカイブには確定した情報が次々と蓄積されていきます。一度 追加された情報を後で修正したり削除したりするコマンドはありません。 一度アーカイブにデータを追加すると、それは永続的に残ります。プロ ジェクトツリーはアーカイブから取り出した情報を加工するための、ま さに作業領域です。作業が一段落したらその結果をアーカイブに追加し ます。これがコミットです。ここでのコマンドは主にプロジェクトツリー の内容を参照したり、その内容を変化させるためのコマンドです。

名前

tla init-tree — 新しいプロジェクトツリーの初期化

用法

tla init-tree [options] [[archive]/version]

説明

このコマンドは引数で指定した VERSION のためのパッチロ グの領域を作ります。呼び出された直後にはこの領域にパッチログ はありません。同時にこの VERSION が import や commit 処理で のデフォルトのアーカイブバージョンになります。

このコマンドを実行すると、{arch}という管理領域が作成さ れます。VERSION のためのパッチログ領域もここに作られます。パッ チログ領域が存在しないバージョンにはそのバージョンのパッチロ グを追加できません。

このコマンドはこれからバージョン管理しようとするディレ クトリを arch の管理下に置くものです。{arch}ディレクトリが作 成される以外既存のファイルに対しては一切変更されません。CVS の場合、リポジトリに対する初期インポート後、リポジトリからの チェックアウト処理によって初めて作業コピーができますが、GNU arch では管理したいファイルのあるディレクトリをそのままプロ ジェクトツリーに変化させることができます。

あるディレクトリをバージョン管理するための最初のステッ プの一つです。tla archive-setup 、tla init-tree、tla make-log、tla import が、典型的な GNU arch での初期ワークフ ローです。

別名

なし

変更: [-W--]

スイッチ

-A, --archive  アーカイブを明示的に指定します
-d, --dir DIR  まず DIR に移動します
--nested       ネストしたプロジェクトツリーを初期化します

hello.cというただ一つのファイルからなるディレクトリを プロジェクトツリーに変えます。既存のファイル—この場合 はhello.c—には一切手を触れずに、{arch}という名前の管理 用ディレクトリが作成されます。hello--proj--1.0 というバージョ ンはあらかじめアーカイブに存在している必要はありませんが、 import前までには作成しておく必要があります。バージョンの作成 についてはtla archive-setupコマンドを参照してください。

$ ls
hello.c
$ tla init-tree hello--proj--1.0
$ ls
hello.c  {arch}
$

CVS対応コマンド

なし


名前

tla tree-root — プロジェクトツリールートの表示

用法

tla tree-root [options] [dir]

説明

DIR または現在のディレクトリを含むプロジェクトツリーの ルートを検索し表示します。GNU arch のプロジェクトツリーのルー トには必ず {arch}管理領域があります。このプログラムは上位ディ レクトリに向かって {arch} ディレクトリが存在しないかどうかを 調べることでプロジェクトツリーのルートを判別します。{arch}管 理領域はプロジェクトツリーのルートにしか存在しません。

--accurate オプションを指定すると以下の3種類の可能性を チェックします。まずプロジェクトツリーがコミットの途中であり、 ツリーのパッチログ領域にログエントリを追加する前に中断された 状態にあるかどうかを調べます。この場合アーカイブに対して実際 にコミットが完了したかどうかを知ることはできず、{arch}ディレ クトリには "++mid-commit" のようなログファイルが残っています。 ツリーがこの状態にある場合にはエラーメッセージを表示して終了 します。

プロジェクトはコミットを中断した状態にありますが、実際 にはコミットが完了しています。この場合 "++commit-definite"の ようなログファイルが残っています。ツリーがこの状態にある場合 にはまずログファイルを正しく設定し、その後ツリールートを表示 し、プログラムを正常に終了します。

プロジェクトツリーのパッチログは完全に更新されている場 合。ツリーがこの状態であれば普通にツリールートを表示し、正常 終了します。

別名

なし

変更: [----]

スイッチ

--accurate      トランザクション途中のツリーに対してエラーを報告します
-s, --silent    ステータスのみを返します

/home/foo/proj という名前のプロジェ クトツリールートに hello.c というファイルとドキュメント用ディ レクトリ doc があります。プロジェクトツリールートで実行して も、doc サブディレクトリで実行しても、プロジェクトツリールー トである /home/foo/proj が返ります。

$ pwd
/home/foo/proj
$ ls
doc  hello.c  {arch}
$ tla tree-root
/home/foo/proj
$ cd doc
$ pwd
/home/foo/proj/doc
$ ls
README.txt
$ tla tree-root
/home/foo/proj
$

CVS対応コマンド

なし


名前

tla tree-version — デフォルトツリーバージョンの表示

用法

tla tree-version [options] [dir]

説明

DIR または現在のディレクトリにあるプロジェクトツリーの デフォルトアーカイブバージョンを表示します。デフォルトアーカ イブバージョンは import、commit、などのコマンドで特にバージョ ンを指定しなかった場合に利用されるものです。ここで言うバージョ ンは CVS で言うリポジトリ名に対応するものです。tla set-tree-version も参照してください。

別名

なし

変更: [----]

スイッチ

なし

プロジェクトツリーのルートでデフォルトツリーバージョン を確認しています。doc サブディレクトリの下で実行しても同じ内 容が返ります。

$ pwd
/home/foo/proj
$ ls
doc  hello.c  {arch]
$ tla tree-version
octopus@bluegate.org--2004/hello--proj--1.0
$

CVS対応コマンド

なし


名前

tla set-tree-version — デフォルトツリーバージョンの設定

用法

tla set-tree-version [options] [archive]/version

説明

DIR または現在のディレクトリにあるプロジェクトツリーの デフォルトバージョンを設定します。デフォルトバージョンは import、commit、などでで特にバージョンを指定しなかった場合に 利用されるものですが、ここで言うバージョンは CVS で言うリポ ジトリ名に対応するものです。tla tree-version も参照してくだ さい。

バージョンを指定する際のアーカイブは通常のコマンドライ ン引数の形で ARCHIVE/VERSION のように指定することもできます し、-A、-R オプションで指定することもできます。tla my-default-archiveのオプションを見てください。

単純な開発ラインの場合、このコマンドを使ってデフォルト バージョンを変更することはほとんどありません。デフォルトバー ジョンはプロジェクトツリー作成時点で一度だけ設定することがほ とんどですが、この一度だけの設定には tla init-tree コマンド の引数として与えることもできるからです。このコマンドは複数の バージョンを同時に内包するような複雑な開発ラインを作る場合に のみ利用されます。

別名

なし

変更: [-W--]

スイッチ

-A, --archive  Override `my-default-archive'
-d, --dir DIR  cd to DIR first

プロジェクトのデフォルトバージョンを変更してから tla tree-version コマンドで確認しています。

$ tla tree-version
octopus@bluegate.org--2004/hello--proj--1.0
$ tla set-tree-version bar@bluegate.org--2004/another--proj--1.0
$ tla tree-version
bar@bluegate.org--2004/another--proj--1.0
$

CVS対応コマンド

なし


名前

tla undo — プロジェクトツリー中内での変更取消

用法

tla undo [options] [revision]

説明

プロジェクトツリーの変更点を退避したあと修正前の状態に 戻します。リビジョン REVISION から DIR にあるプロジェクトツ リーの内容の差分をチェンジセットの形で求め、PATCH-DIR ディレ クトリに保存します。PATCH-DIRディレクトリはあらかじめ存在し ていてはいけません。次にこのパッチを DIR にあるプロジェクト ツリーに対して逆向きに適用します。この結果 DIR に対して加え られたローカルな変更点は取り消され、その修正点を示すチェンジ セットは扱いやすい形で保存されます。

REVISION が指定されない場合、ツリーが利用しているデフォ ルトバージョンの直近の祖先まで戻ります。REVISION が VERSION の形で指定された場合はその VERSION 中の直近の祖先を利用しま す。

DIR が指定されなければ "." を仮定します。

PATCH-DIRが指定されなければ ,,undo-* という形の一時ファ イル名が利用されます。

--no-output が指定されるとチェンジセットは保存されませ ん。"tla redo", "tla changes" も参照してください。

別名

なし

変更: [-W--]

スイッチ

-A, --archive           アーカイブを明示的に指定します
-d, --dir DIR           DIR に移動してから処理を開始します
-o, --output PATCH-DIR  チェンジセットを PATCH-DIR に保存します
-n, --no-output         チェンジセットを保存しません
-N, --forward           `patch'コマンドに ---forward オプションを渡します
-q, --quiet             計算途中の進行状況を表示しません
-changeset

以下ではプロジェクトツリーは patch-1 まで開発が進んだ hello--proj--1.0 にローカルな修正を加えた状態です。これを patch-1 の状態まで戻すために tla undo を実行します。実行前に、 プロジェクトツリーの履歴と、最新リビジョン patch-1 との間の 差分を確認しています。また実行後に ls コマンドで ,,undo-1 ディ レクトリが作成されていることを確認しています。

$ tla abrowse --desc
octopus@bluegate.org--2004
  hello
    hello--proj
      hello--proj--1.0

        base-0    (initial import)
          Mon Apr  5 11:36:16 JST 2004      foo bar <octopus@bluegate.org>
          initial import

        patch-1    (simple changeset)
          Mon Apr  5 11:37:45 JST 2004      foo bar <octopus@bluegate.org>
          add a printf() line.

$ tla changes --diffs
* looking for octopus@bluegate.org--2004/hello--proj--1.0--patch-1 to
compare with
* comparing to octopus@bluegate.org--2004/hello--proj--1.0--patch-1
M  hello.c

* modified files

--- orig/hello.c
+++ mod/hello.c
@@ -1,4 +1,4 @@
-main()
+void main(int argc, char* argv[])
 {
        printf("hello world\n");
 }

$ tla undo
* linting the source tree
* reverting changes
M   hello.c
$ ls
,,undo-1  hello.c  {arch}
$

CVS対応コマンド

なし


名前

tla redo — プロジェクトツリー中の変更の再適用

用法

tla redo [options] [changeset]

説明

CHANGESET をプロジェクトツリーに適用後そのCHANGESETを 削除します。CHANGESET が指定されなければプロジェクトツリー中 にある ,,undo-N の形のディレクトリで N が最も大きいものが利 用されます。--keep を指定するチェンジセットディレクトリは削 除されません。"tla undo", "tla apply-changeset" も参照してく ださい。

別名

なし

変更: [-W--]

スイッチ

-N, --forward  pass the --forward option to `patch'
-k, --keep     do not delete the patch
-q, --quiet    no progress reports while computing changeset
-d, --dir DIR  Operate on project tree in DIR (default `.')

tla undo の項の例を実行した直後の状態にあるとします。 tla redo を利用して undo の結果を再びプロジェクトツリーに適 用しています。実行前に ,,undo-1 ディレクトリを確認し、tla changesコマンドでプロジェクトツリーが patch-1 リビジョンと一 致していることを確認しています。tla redo 後には hello.c に再 びローカルな修正が加えられ、tla changes の結果でそれを確認し ています。

$ ls
,,undo-1  hello.c  {arch}
$ tla changes
* looking for octopus@bluegate.org--2004/hello--proj--1.0--patch-1 to
compare with
* comparing to octopus@bluegate.org--2004/hello--proj--1.0--patch-1
$ tla redo
* linting the source tree
M   hello.c
$ tla changes
* looking for octopus@bluegate.org--2004/hello--proj--1.0--patch-1 to
compare with
* comparing to octopus@bluegate.org--2004/hello--proj--1.0--patch-1
M  hello.c
$ ls
hello.c  {arch}
$

CVS対応コマンド

なし


名前

tla changes — プロジェクトツリーのローカルな変更点の表示

用法

tla changes [options] [revision] [-- limit...]

説明

DIR にあるプロジェクトツリー(または現在のディレクトリ) と REVISION との間の差分をパッチ形式で表示します。デフォルト のリビジョンは、プロジェクトツリーにある指定されたバージョン に関するパッチログのうちで一番最後のものになります。デフォル トのアーカイブとバージョンは "tla tree-version" で表示される ものが利用されます。このコマンドは自分の加えた修正点を確認す るためによく利用されます。重要なコマンドの一つです。

別名

なし

変更: [----]

スイッチ

-A, --archive     Override `my-default-archive'.
-d, --dir DIR     Change to DIR first.
-o, --output DIR  Save changeset in DIR (implies --keep).
-v, --verbose     Verbose changeset report.
-q, --quiet       Suppress progress information
--diffs           Include diffs in the output.
-k, --keep        Don't remove the output directory
                    on termination.

tla undo, tla redo の例を参照してください。

CVS対応コマンド

なし


名前

tla file-diffs — ファイルに対するローカルな変更点の表示

用法

tla file-diffs [options] file [revision]

説明

FILE と、キャッシュにされた REVISION 中の対応するファ イルとの差異を表示します。指定したバージョンのデフォルトのパッ チレベルはプロジェクトツリーにあるそのバージョンのパッチで一 番最後のものです。デフォルトアーカイブとデフォルトバージョン は "tla tree-version" で表示されるものになります。

別名

なし

変更: [----]

スイッチ

-A, --archive   アーカイブを明示的に指定します
-N, --new-file  存在しないファイルをゼロバイトのファイルとして扱います

特定のファイルに対する修正点を表示します。これは GNU diff コマンドの出力と同じ形のものです。

$ tla file-diffs hello.c
--- orig/hello.c
+++ mod/hello.c
@@ -1,4 +1,4 @@
-main()
+void main(int argc, char* argv[])
 {
        printf("hello world\n");
 }
$

CVS対応コマンド

なし

プロジェクトツリーインベントリコマンド

ここでは GNU arch 独自の概念であるインベントリを扱うための コマンド群を説明します。インベントリは CVS など他のバージョン管 理システムでは、少なくとも明示的には存在しない概念です。インベン トリとは一言で言うと「ファイルの名称が変更されてもその変化 を追跡し続けるためのしくみ」のことです。この仕組みを実現す るためにバージョン管理対象となるファイルのすべてにインベントリid と呼ばれるお互いを区別するキーが割り当てられます。GNU arch はこ のキーを手がかりにして、マージ処理などで名前の違う二つのファイル が同一起源のものであるかどうかを判別します。

名前

tla inventory — プロジェクトツリーのインベントリ一覧

用法

tla inventory [options] [--] [dir]*

説明

プロジェクトツリーのインベントリの一覧を表示します。オ プションを指定することでインベントリidで管理されているファイ ル以外のファイルも表示することができます。プロジェクトツリー 中のファイルは、インベントリidの付与規則や、{arch}管理領域に ある=tagging-method ファイル、そのほかの制御ファイルの状態に よっていくつかのグループに分類されます。この規則は歴史的な経 緯もあって非常に複雑ですが、tla inventory コマンドを使えばそ れぞれのファイルがどのグループに分類されているかを確認するこ とができます。

-r または --report を使うと、カテゴリオプション (--sourceなど)はそれらのファイルにたいしてのみ表示するように なります。オプションがなければすべてのセクションとファイルを 含んだ内容が表示されます。-d, -f, -b オプションは相互に排他 的です。ディレクトリが precious, junk, unrecognized である場 合はディレクトリ名称自身のみが表示されます—その内容は 検索されません。

すべてのコマンドオプションは対応するカテゴリオプション を暗黙に含んでいます(たとえば "--source-command" は "--source"を含みます)。コマンドの終了ステータスは無視されま す。

このコマンドは、プロジェクトツリーの初期インポート時に よく利用されます。初期インポート時にはどのファイルがソースファ イル、つまりバージョン管理対象として GNU arch が認識するかが 非常に重要になるからです。またインポート後でもすべてのソース コードに対して一括した処理をしたいような場合にunixのxargsコ マンドとの組み合わせでよく利用されます。また tla tree-lint がエラーになる場合には、このコマンドの表示で詳しい原因がつか めるのが普通です。

別名

なし

変更: [----]

スイッチ

このコマンドは非常に豊富なスイッチがあります。

-s, --source        ソースファイルの一覧を表示します
-p, --precious      プレシャスファイルの一覧を表示します
-b, --backups       バックアップファイルの一覧を表示します
-j, --junk          ジャンクファイルの一覧を表示します
-u, --unrecognized  アンレコグナイズファイルの一覧を表示します
-t, --trees         ネストしたツリーのルートの一覧を表示します

-d, --directories   ディレクトリのみを表示します
-f, --files         ディレクトリ以外のファイルのみを表示します
-B, --both          ディレクトリとファイルの両方を表示します
--kind              ファイル種別を表示します

--all               GNU arch 管理領域のファイルも表示します
--nested            ネストしたツリーも表示します

--ids               id と共に表示します (ソースファイルのみ)
--untagged          id のないファイルも表示します

--explicit          明示的なidを使います
--implicit          暗黙のidを認めます
--tagline           タグラインidを認めます
--names             名前ベースのファイルidを使います

プロジェクトのルートに ,,undo-1 というディレクトリがあ りますが、これがソースファイルとして認識されないことを確認し ています。",," で始まるファイルはすべて無条件にジャンクファ イルとして扱われるという規則があります。ファイルの分類とイン ベントリについては(XXX)を見てください。

$ ls
,,undo-1  hello.c  {arch}
$ tla inventory
S  hello.c
$

もう一つの例は、プロジェクトツリーのソース全体を一つに まとめて、リリース用 tar ファイルを作るような場合です。説明 のために tools.c というファイルを追加してあります:

$ ls
,,undo-1  hello.c  tools.c  {arch}
$ tla inventory -s  | tar -T- -zcvf release.tar.gz
hello.c
tools.c
$ ls
,,undo-1  hello.c  release.tar.gz  tools.c  {arch}
$ tar ztvf release.tar.gz
-rw-rw-r-- foo/foo          91 2004-04-05 14:23:06 hello.c
-rw-rw-r-- foo/foo          54 2004-04-05 14:29:31 tools.c

ソースコード中の文字列を検索します。この場合単純に find プログラムと grep コマンドを組み合わせると {arch}内のファ イルなども検索対象となってしまいます。tla inventory と xargs コマンドを組み合わせて以下のようにするとうまくいきます。たと えばソースコード中の "#ifdef" 行全体を取得したい場合なら:

$ tla inventory -s | xargs -l grep -nH ifdef
hello.c:6:#ifdef
tools.c:2:#ifdef
tools.c:8:#ifdef
$

CVS対応コマンド

なし


名前

tla tree-lint — プロジェクトツリーの整合性をチェックします

用法

tla tree-lint [options] [dir]

説明

失われたファイル、タグづけされていないファイル、重複し たインベントリid、そして名前規約で認識することができないファ イルを調べます。デフォルトではこれらのテストで失敗するすべて のファイルを一覧表示します。オプションでどれか特定のテストを 明示的に有効にするとそれ以外のテストは省略されます。つまり引 数なしの tla tree-lint は tla tree-lint -sutmd と同じです。

別名

なし

変更: [----]

スイッチ

-s, --broken-symlinks     壊れたシンボリックリンクの一覧を表示します
-u, --unrecognized-files  名前規約に違反しているファイルの一覧を表示します
-t, --untagged-files      インベントリidがないファイルの一覧を表示します
-m, --missing-files       ファイルに対応しないインベントリidの一覧を表示します
-d, --duplicate-ids       重複したインベントリidの一覧を表示します
--strict                  異常があった場合にゼロ以外の終了ステータスで抜けます

プロジェクトツリー中に hello.c という唯一のファイルが あります。このファイルはタグラインによるインベントリidを持っ ていて、その値は i_0211e195-e8cb-4604-bfa8-8a96425b9cd2 です。 もう一つのソースコードを作成するため、スクラッチから作らず hello.c をコピーして hello_sub.c としましたが、同じインベン トリidを持つため tree-lint に怒られます。対処方法としては hello_sub.c 用に別のインベントリidを生成し arch-tag: ライン を修正するだけです。インベントリidの生成についてはXXXを見て ください。

$ ls
hello.c  {arch}
$ tla inventory --ids
S  hello.c      i_0211e195-e8cb-4604-bfa8-8a96425b9cd2
$ cp hello.c hello_sub.c
…
$ tla tree-lint
Duplicated ids among each group of files listed here:

hello.c i_0211e195-e8cb-4604-bfa8-8a96425b9cd2
hello_sub.c

$

CVS対応コマンド

なし


名前

tla id — ファイルのインベントリid の表示

用法

tla id [options] file...

説明

ファイルのインベントリidを、オプションで指定した方法で 表示します。

別名

なし

変更: [----]

スイッチ

--implicit      暗黙のidタグ付けの方法を使います
--tagline       タグラインのタグ付けを使います(規定値)
--explicit      明示的なタグ付けの方法を使います
--names         名前によるidタグ付けの方法を使います
--silent        ステータスのみを返し表示しません

hello.c という tagline でタグづけされたファイルに対し て tla id コマンドを実行してみましょう:

$ ls
hello.c  {arch}
$ cat hello.c
main()
{
        printf("hello world\n");
}

/*
arch-tag: 0211e195-e8cb-4604-bfa8-8a96425b9cd2
*/
$ tla id hello.c
hello.c i_0211e195-e8cb-4604-bfa8-8a96425b9cd2
$

実験的に arch-tag 行を削除してもう一度 tla id を実行し てみます:

$ cat hello.c
main()
{
        printf("hello world\n");
}

/*
   arch tag has removed.
*/
$ tla id hello.c

id: untagged file
  hello.c

$

今度は明示的なタグをつけてみましょう:

$ tla add-id hello.c
$ tla id hello.c
hello.c x_foo_bar_<octopus@bluegate.org>_Mon_Apr__5_14:56:03_2004_12028.0
$

'x_ … 以下は tla が内部的に生成した明示的なイン ベントリid です。他の tla ユーザのどのようなインベントリidと も衝突しないように、tla my-id の内容と、現在のシステム時刻を 組み合わせたユニークな文字列を生成していることがわかります。

CVS対応コマンド

なし


名前

tla id-tagging-method — プロジェクトツリーのタグ付けの方法の表示・変更

用法

tla id-tagging-method [options] [method]

説明

DIR中(または現在のディレクトリで)のソースファイルを識 別する方法を表示または変更します。変更する場合には METHODを 指定しますが、これは以下のどれかになります:

表 C.1. idタグづけの方法

名前意味
namesファイルパス名だけでファイルを識別します
implicitファイルパス名でファイルを識別しますがインベン トリタグによる方法も認めます
explicit明示的なタグを要求します
taglineパス名、明示的な方法、arch-tag:による 方法、の組み合わせです

タグ付けを方法を表示させる場合、--strict オプションを 指定したのにタグ付けの方法が明示的に指定されていない場合エラー が表示されます。

このコマンドはプロジェクトツリーの初期インポート時によ く再設定されます。特に理由がなければ tagline の方法を使うこ とが推奨されますが、ユーザが意識して設定するように、デフォル トでは explicit になっています。初期インポート時にやらなくて はならない重要なことは、このコマンドの実行と {arch}/=tagging-methodの編集です。

別名

なし

変更: [--C-]

スイッチ

-d, --dir DIR  まず DIR に移動します
--strict       タグづけの方法が設定されない場合エラーで返ります

タグ付けの方法を確認し、explicit から tagline に変更し ます。これに応じて tla id の出力も変わります。

$ tla id-tagging-method
explicit
$ tla id-tagging-method tagline
method set: tagline
$ tla id-tagging-method
tagline
$

CVS対応コマンド

なし


名前

tla add-id — 明示的なインベントリidの追加

用法

tla add-id [options] file ...

説明

明示的なインベントリid を FILE に対して振ります。この ファイルは通常のファイル、シンボリックリンク、ディレクトリ、 いずれであってもかまいません。

別名

なし

変更: [-W--]

スイッチ

-i, --id ID    自動的に生成されるidのかわりに特定のIDを指定します

hello.c というファイルに明示的なタグを自動生成した結果 です

$ tla add-id hello.c
$ tla id hello.c
hello.c x_foo_bar_<octopus@bluegate.org>_Mon_Apr__5_15:37:15_2004_12146.0
$

CVS対応コマンド

なし


名前

tla delete-id — 明示的なインベントリidを削除します

用法

tla delete-id [options] file ...

説明

FILE に付与されていた明示的なインベントリidを削除しま す。ファイルは通常ファイル、シンボリックリンク、ディレクトリ のいずれでもありえます。

別名

なし

変更: [-W--]

スイッチ

なし

すでに振られていた明示的なタグを削除します。hello.c に は arch-tag によるタグが振られていたので削除後はこちらが有効 になっているのがわかります。

$ tla id hello.c
hello.c x_foo_bar_<octopus@bluegate.org>_Mon_Apr__5_15:37:15_2004_12146.0
$ tla delete-id hello.c
$ tla id hello.c
hello.c i_0211e195-e8cb-4604-bfa8-8a96425b9cd2
$

CVS対応コマンド

なし


名前

tla move-id — 明示的なインベントリidの移動

用法

tla move-id [options] from to

説明

FILE に付与されている明示的なインベントリid を別のファ イルのインベントリidに移動します。このコマンドは、いままであ るファイルを指していたインベントリidで、別のファイルを指すよ うにしたい場合に利用します。このコマンドはインベントリidの情 報を変更するだけであって、指されているファイルの名称を変更す るのではないことに注意してください。指されているファイルの名 称を変更すると共に、そのインベントリも移動させるtla mv との 違いに注意してください。tla move-id は tla mv よりも原始的で す。このコマンドを利用するのは非常に稀です。

別名

なし

変更: [-W--]

スイッチ

なし

あまり実践的な例ではありませんが、foo.c と bar.c とい う二つの明示的なタグをもつファイルがプロジェクトツリーにある としましょう。いま patch-3 の状態にあり、ここからローカルな 修正は加えていません。

$ ls
bar.c  foo.c  {arch}
$ tla inventory --ids
S  bar.c  x_foo_bar_<octopus@bluegate.org>_Mon_Apr__5_15:48:47_2004_12194.0
S  foo.c  x_foo_bar_<octopus@bluegate.org>_Mon_Apr__5_15:48:43_2004_12193.0
$ tla changes
* looking for octopus@bluegate.org--2004/test--proj--1.0--patch-3 to compare with
* comparing to octopus@bluegate.org--2004/test--proj--1.0--patch-3
$

この状態で foo.c の明示的なidを bar.c に移してみます

$ tla move-id foo.c bar.c
$ tla changes
* looking for octopus@bluegate.org--2004/test--proj--1.0--patch-3 to compare with
* comparing to octopus@bluegate.org--2004/test--proj--1.0--patch-3
D  .arch-ids/bar.c.id
D  bar.c
=> .arch-ids/foo.c.id   .arch-ids/bar.c.id
=> foo.c        bar.c
$

コマンド実行後 tla changes の出力を見ると、foo.c とい うファイルが bar.c に名称変更され、さらに bar.c という元のファ イルが削除されてしまったという内容になっています。これは foo.c のアイデンティティーを表すインベントリidで bar.c を指 すようにしたためです。

CVS対応コマンド

なし


名前

tla mv — ファイル(あるいはディレクトリ、シンボリックリン ク)を移動と、付随する明示的なインベントリidの移動

用法

tla mv [options] from to
tla mv [options] from1 from2 ... dir

説明

このコマンドは Unix コマンド mv(1) と同じ意味を持ちま すが、タグづけの方法を問わず tla プロジェクトツリー中の任意 のファイルの移動を正しく行います。これは明示的にタグづけされ たファイル以外では mv(1)そのものですが、明示的にタグづけされ たファイルの場合にはそのインベントリid情報ファイルも含めた移 動を行います。これで移動後のファイルが移動前と同じインベント リidを持つことを保証します。

明示的なインベントリidを持つファイルを間違って unix コ マンドの mv(1) によって移動してしまった場合には、元のインベ ントリid情報ファイルが孤立してしまいます。この場合でも tla move-idを利用すれば修復することができます。いずれにしてもこ のコマンドはプロジェクトツリー内にしか書き込みが発生しないの で、どうしてもわからなくなった場合には tla undo すれば良いだ けの話しです。

別名

なし

変更: [-W--]

スイッチ

なし

いま、あるバージョンの patch-4 にいます。唯一のファイ ル foo.c がプロジェクトツリー内にあり、明示的なタグによって タグづけされています。

$ ls
foo.c  {arch}
$ tla inventory --ids
S  foo.c        x_foo_bar_<octopus@bluegate.org>_Mon_Apr__5_15:57:35_2004_12242.0
$ tla changes
* looking for octopus@bluegate.org--2004/test--proj--1.0--patch-4 to compare with
* comparing to octopus@bluegate.org--2004/test--proj--1.0--patch-4
$

ここで tla mv コマンドを使って foo.c を bar.c という名 前に変更してみます。

$ tla mv foo.c bar.c
$ tla inventory --ids
S  bar.c        x_foo_bar_<octopus@bluegate.org>_Mon_Apr__5_15:57:35_2004_12242.0
$

変更後の bar のインベントリidが foo.c と同じものである ことに注意してください。ここで tla changes を実行すると、GNU arch が foo.c -> bar.c のファイル名称変更を正しく認識してい ることがわかります。

$ tla changes
* looking for octopus@bluegate.org--2004/test--proj--1.0--patch-4 to compare with
* comparing to octopus@bluegate.org--2004/test--proj--1.0--patch-4
=> .arch-ids/foo.c.id   .arch-ids/bar.c.id
=> foo.c        bar.c
$

今度は unix コマンドの mv(1) で直接 foo.c を bar.c に 変更してみましょう:

$ mv foo.c bar.c
$ tla inventory --ids
P? bar.c        ???
$ tla changes
* looking for octopus@bluegate.org--2004/test--proj--1.0--patch-4 to compare with
* comparing to octopus@bluegate.org--2004/test--proj--1.0--patch-4
D  foo.c

foo.c に対応した明示的なインベントリidを同時に移動しな かったので bar.c が孤立してしまいました。"P?" がこれを示して います。また foo.c から bar.c への名称変化を把握することがで きずに tla changes の表示で foo.c が削除されたと表示されてい ます。

CVS対応コマンド

なし


名前

tla explicit-default — デフォルトインベントリidの表示と変更

用法

tla explicit-default [options] [ID-PREFIX]

説明

DIRあるいは現在のディレクトリにあるすべてのファイルに 対して、明示的なインベントリidを持たないものに対して以下をデ フォルトのインベントリidとして利用します:

ID-PREFIX__BASENAME

ここで BASENAME はファイルのベース名です。引数がなけれ ば現在設定されている ID-PREFIX を表示します。デフォルトでは、 このコマンドで ID-PREFIX を表示、削除、設定する場合、いずれ も「強いデフォルト」が操作対象となります。強いデ フォルトとは、暗黙のインベントリidを上書きする性質をもったデ フォルトインベントリidです。

--weak を指定すると明示的なインベントリidによって上書 きされるような「弱いデフォルト」を設定、あるいは 表示します。--dont-care オプションを指定すると、該当ディレク トリに、"tla tree-lint"のようなコマンド時に表示されないよう な unidged files (XXX)を設定(あるいは -d オプションが指定さ れていればクリア)されます。

別名

なし

変更: [-W--]

スイッチ

-D, --dir DIR    cd to DIR first
-d, --delete     remove the default
-s, --strong     use the strong default (default)
-w, --weak       use the weak default
--dont-care      use the dont-care default

CVS対応コマンド

なし


名前

tla id-tagging-defaults — =tagging-method のデフォルト内容の表示

用法

tla id-tagging-defaults [options]

説明

=tagging-method ファイルを初期化する際に利用されるテン プレートの内容を表示します。

注意

=tagging-methodファイルは、プロジェクトツリーの {arch}管理領域に置かれるファイルで、[1]インベントリidのタ グづけ方法の指定と、[2]プロジェクトツリー内のどのファイル をバージョン管理対象とするか、についての設定をするためのも のです。ファイルの名前とはうらはらに[2]の役割も担っている ことに注意してください。

別名

なし

変更: [----]

スイッチ

なし

単に引数なしで実行すれば、=tagging-method ファイルのデ フォルト値が得られます。

$ tla id-tagging-defaults
# id tagging method
#
# This determines how "inventory ids", strings conveying
# logical file identity, are computed for each file, directory

    …

source ^[_=a-zA-Z0-9].*$

# Any files not classified by the above rules are classified as unrecognized.
# Traversal does not descend into unrecognized directories.

$

CVS対応コマンド

なし

パッチセットコマンド

この節のコマンドはある意味で GNU arch コマンドの中でもっと 基本的で、もっとも原始的なコマンドです。いわば GNU arch の心臓と もいうべきコマンド群です。その内容は、二つのツリーの差分を計算し チェンジセットとして求めること、逆にそのように得たチェンジセット を元のツリー、あるいは別の任意のツリーに対して適用するコマンドで す。GNU diff, GNU patch を一般化したコマンドであると考えればよい でしょう。単にツリーと書いたことに注意してください。ここにはまだ 「プロジェクトツリー」の概念も、「リポジトリ 」のような概念も現れません。あるのは生のツリーだけです。こ の節のコマンドは任意のツリーに対して適用することができるものなの です。

名前

tla changeset — チェンジセットの計算

用法

tla changeset [options] ORIG MOD DEST [files]

説明

二つのツリー間のチェンジセットを求めます。引数 ORIG と MOD はいずれもディレクトリで両者の間のチェンジセットがディレ クトリDESTに求まります。DESTはあらかじめ存在してはなりません。 これとちょうど逆の処理にあたる tla apply-changeset も見てく ださい。

注意

チェンジセットは GNU patch を拡張した概念なので、文脈 からその意味がはっきりする場合には単にパッチと呼ぶこともあり ます。GNU patch は単一のファイルですが、チェンジセットはディ レクトリとして定義されていることに注意してください。これはプ ログラムで扱いやすかったためたまたまそのように設計されただけ で深い意味はありません。これと等価の単一ファイルのチェンジセッ ト—これをシリアル化チェンジセットといいます—を定 義することは、GNU arch の興味深い拡張になるでしょう。

別名

mkpatch

変更: [----]

元のツリーには変更はありませんが、新しい DEST というディ レクトリが作られ、そこには書き込みます。

スイッチ

--file-list FILES      指定したファイルについての差分のみを記録します

あまり実践的な例ではありませんが説明のために二つのディ レクトリ a, b を用意しました。いずれのディレクトリにも file1.txt という名前の唯一のファイルがあります。b のほうにあ るものは a にあるものに一行追加しただけのものです。

$ ls
a  b
$ ls
a  b
$ find
.
./a
./a/file1.txt
./b
./b/file1.txt
$ cat a/file1.txt
aaaaa
bbbbb
$ cat b/file1.txt
aaaaa
bbbbb
ccccc
$

このふたつのディレクトリ a, b の間の差分をチェンジセッ トの形でディレクトリ c に求めてみます。

$ tla changeset a b c
M  file1.txt
$ ls
a  b  c
$

ディレクトリ c が作成されました。このディレクトリは GNU arch で定義されたチェンジセットの形式になっています。

$ ls c
mod-dirs-index              new-files-archive  original-only-dir-metadata
mod-files-index             orig-dirs-index    patches
modified-only-dir-metadata  orig-files-index   removed-files-archive

今回場合、一番重要な情報は patches ディレクトリの中に あります。

$ ls c/patches
file1.txt.patch
$ cat c/patches/file1.txt.patch
--- orig/file1.txt
+++ mod/file1.txt
@@ -1,2 +1,3 @@
 aaaaa
 bbbbb
+ccccc
$

確かにファイルの差分が格納されています。この例で、引数 として与えた a, b のディレクトリはプロジェクトツリーではなく 一般的なディレクトリであることに注意してください。このコマン ドは任意のツリーの間のチェンジセットを計算することができます。

CVS対応コマンド

なし


名前

tla apply-changeset — チェンジセットの適用

用法

tla apply-changeset [options] CHANGESET TARGET

説明

CHANGESET にあるチェンジセットを TARGET に適用します。 CHANGESETはGNU arch チェンジセットの定義を満たす形のディレク トリ、TARGET は任意のディレクトリです。

別名

dopatch

変更: [----]

このコマンドにはプロジェクトツリーの概念が現れないので 上記の形でうまく表現できませんが、引数 TARGET のツリーには書 き込みがおこります。

スイッチ

-N, --forward  pass the --forward option to `patch'
-r, --reverse  Apply the changeset in reverse

tla changeset の例での続きです。いま、a, b, c というディ レクトリがあり、a と b の差分のチェンジセットが c にあります。 この c を a に適用してみます。

$ ls
a  b  c
$ tla apply-changeset c a
M   file1.txt
$

これで a は b と同じツリーになっているはずです:

$ diff -ur a b
$

確かにそうなっています。

CVS対応コマンド

なし


名前

tla show-changeset — チェンジセットの内容を可読形式で表示

用法

tla show-changeset [options] [dir]

説明

チェンジセットの要約を人間が読める形式で表示します。

別名

なし

変更: [----]

スイッチ

--diffs        include diff output

tla changeset, tla apply-changeset の例でできたチェン ジセット c をこのコマンドで表示してみます:

$ ls
a  b  c
$ tla show-changeset c
* modified files

    file1.txt

$

より詳細な情報が欲しい場合には --diffs オプションを指 定します:

$ tla show-changeset --diffs c
* modified files

--- orig/file1.txt
+++ mod/file1.txt
@@ -1,2 +1,3 @@
 aaaaa
 bbbbb
+ccccc

$

CVS対応コマンド

なし

アーカイブトランザクションコマンド

このグループのコマンドはアーカイブに新しいバージョン用の場 所を確保したり、そこに実際のデータを初期インポートしたり、その後 におきた修正点をコミットしたりするような、アーカイブに対する書き 込み処理と、逆にすでにアーカイブにある特定のリビジョンの内容をプ ロジェクトツリーの形に取り出したり、あるリビジョンと次のリビジョ ンの差分であるチェンジセットをその固有のディレクトリ形式で抽出し たりするコマンドです。

名前

tla make-archive — 新しいアーカイブディレクトリの作成

用法

tla make-archive [options] [name] location

説明

NAME はアーカイブのグローバルな名前です。それは完全な emailアドレスの形で始まり、その後にオプションとして "--"と、 文字、数字、'.'、'-'の任意の並びを続けることができます。-- mirrorオプションをつけると、新しいアーカイブを MASTERのミラー として登録します。ミラーに対しては通常のコミットは失敗します が、'tla archive-mirror'コマンドを使ってMASTERの内容をミラー に同期することができます。

二つの特別な利用方法があります以下のコマンド

tla make-archive --mirror MASTER LOCATION

は、以下と同じ意味になります:

tla make-archive --mirror MASTER MASTER-MIRROR LOCATION

そのため、"tla archive-mirror MASTER"は MASTERからの内 容を新たに作ったミラーに反映することになります。

さらに以下のコマンド:

tla make-archive --mirror-from MASTER-SOURCE LOCATION

は、以下と同じ意味になります:

tla make-archive --mirror MASTER-SOURCE MASTER LOCATION

そのため、"tla archive-mirror MASTER"は MASTER-SOURCE からの変更を新たに作ったミラーに反映することになります。

ティップ

make-archive と似たコマンドに register-archive があ ります。これは既存のアーカイブロケーションとアーカイブ名を結 び付けるだけのコマンドです。make-archive はアーカイブ領域を 初期化すると同時に登録もします。そのため make-archive したアー カイブはあらためて register-archive する必要はありません。

アーカイブはローカルファイルシステムのどの場所にも作成 することができますが、今後複数のアーカイブを作るかも知れない ことを見越してアーカイブ専用の空のサブディレクトリを作り、そ こに作成することが推奨されています。またこのサブディレクトリ 名称は{archives}のような名前が良いとされていますが、通常の文 字のみを含むような名前でももちろん全くかまいません。

このコマンドはアーカイブの入れ物を作るだけで、まだ何も 含まれていません。具体的なバージョン管理を始める場合には、 tla archive-setup などのコマンドを使って、このアーカイブ中に バージョンを作成する必要があります。こうしてできたアーカイブ バージョンが開発ラインの入れ物になります。通常make-archiveコ マンドはそれほど頻繁には利用しません。archive-setupコマンド のほうは新しい管理対象の開発ラインをアーカイブに追加するたび に呼び出されます。

別名

なし

変更: [A---]

スイッチ

-m, --mirror MASTER              create mirror of specified archive
-M, --mirror-from MASTER-SOURCE  create pull-based mirror of specified archive
-l, --listing                    Keep .listing files up-to-date in this archive.
-s, --signed                     GPG sign the contents of this archive.

すでに octopus@bluegate.org--2004 というアーカイブがあり、 それとは別の用途、たとえばプライベートなアーカイブを作ること にしましょう。

$ pwd
/home/foo
$ ls
Maildir  cset  proj  {archives}
$ tla archives
octopus@bluegate.org--2004
    /home/foo/{archives}/octopus@bluegate.org--2004
$ ls /home/foo/\{archives\}/
octopus@bluegate.org--2004
$ tla make-archive octopus@bluegate.org--2004-private
	  /home/foo/\{archives\}/octopus@bluegate.org--2004-private
$ tla archives
octopus@bluegate.org--2004
    /home/foo/{archives}/octopus@bluegate.org--2004
octopus@bluegate.org--2004-private
    /home/foo/{archives}/octopus@bluegate.org--2004-private

警告

この例ではいずれのアーカイブも、アーカイブ名と実際の アーカイブ位置のディレクトリの名前が等しくなっています。 GNU arch ではこのように必ず二つの名称を一致させなくてはな らないという決まりはありませんが、名前に関する混乱をできる だけ避けるために特に理由がなければ名前を同じにしておくと良 いでしょう。

CVS対応コマンド

なし


名前

tla archive-setup — 新しいカテゴリ、ブランチ、バージョンの作成

用法

tla archive-setup [options] [version ...]

説明

指定したカテゴリ、ブランチ、バージョンをアーカイブに作 ります。たとえば空のアーカイブを指定せずに以下を実行すると:

$ tla archive-setup  proja--devo--1.0 projb

tla my-default-archive で示されるアーカイブに、アーカ イブバージョン proja--devo--1.0 とカテゴリ projb を作成しま す。--file オプションが指定されると作成されるアイテムのリス トがファイルから読み込まれます('-'を指定すると標準入力からに なります)。--file オプションは同時に --branches も指定するこ とができますが、この場合入力は一行につきふたつのカラムが必要 です—作成しようとしているバージョンとそこにタグづけす る際の元になるバージョンです。たとえば以下のような行を含むファ イル:

proja--devo--1.0  his@foo.com/proja--devo--1.0

これを--branchesオプション付きで実行すると archive-setupコマンドはでデフォルトアーカイブ中に proja とい うバージョンを作り、そこに base-0 リビジョンを作りますが、こ れはhis@foo.com のアーカイブにある最後のリビジョンへのタグと します。この機能は、既存のアーカイブからのブランチを新しいアー カイブ中に一度にまとめて作成するような場合に便利です。

別名

なし

変更: [A---]

スイッチ

-A, --archive    Override `my-default-archive'
-f, --file FILE  read the list of desired versions from FILE
-b, --branches   make base-0 tags
-c, --cache      archive cache when creating base-0 tags

hello--proj--1.0 というバージョンのみを持っている octopus@bluegate.org--2004アーカイブに bug--goo--1.0 というバー ジョンを追加してみましょう:

$ tla abrowse
octopus@bluegate.org--2004
  hello
    hello--proj
      hello--proj--1.0
        base-0 .. patch-5

$ tla archive-setup bug--goo--1.0
* creating category octopus@bluegate.org--2004/bug
* creating branch octopus@bluegate.org--2004/bug--goo
* creating version octopus@bluegate.org--2004/bug--goo--1.0
$ tla abrowse
octopus@bluegate.org--2004
  bug
    bug--goo
      bug--goo--1.0

  hello
    hello--proj
      hello--proj--1.0
        base-0 .. patch-5

$

アーカイブの内部をざっと見るには tla abrowse を使うの が常套手段です。

CVS対応コマンド

なし


名前

tla make-category — 新しいカテゴリの作成

用法

tla make-category [options] category

説明

指定したアーカイブ中に新しいカテゴリ CATEGORY を作りま す。あらかじめそのカテゴリが存在していてはいけません。

別名

なし

変更: [A---]

スイッチ

-A, --archive  Override `my-default-archive'

省略します。かわりに tla archive-setup を利用すること をお勧めします。

CVS対応コマンド

なし


名前

tla make-branch — 新しいブランチの作成

用法

tla make-branch [options] branch

説明

指定したアーカイブに新しいブランチ BRANCH を作ります。 同じ名前のブランチがカテゴリに存在していてはいけません。 BRANCH は C--B のように指定します。ここで C はカテゴリ名、B はブランチ名です。

別名

なし

変更: [A---]

スイッチ

-A, --archive  Override `my-default-archive'

省略します。かわりに tla archive-setup を利用すること をお勧めします。

CVS対応コマンド

なし


名前

tla make-version — 新しいバージョンの作成

用法

tla make-version [options] version

説明

指定したアーカイブに VERSION という名前のバージョンを 作ります。同じ VERSION が同一のカテゴリ、ブランチに存在して いてはいけません。VERSION の指定は C--B--V のようにします。 ここで C, B, V はそれぞれカテゴリ名、ブランチ名、バージョン 名です。

別名

なし

変更: [A---]

スイッチ

-A, --archive  Override `my-default-archive'

省略します。かわりに tla archive-setup を利用すること をお勧めします。

CVS対応コマンド

なし


名前

tla import — ソースコード全体を含む完全な base-0 リビジョンを 作ります

用法

tla import [options] [[archive]/version]

説明

DIR(あるいは現在のディレクトリ)にあるプロジェクトツリー の最初のリビジョンを保存します。新規にプロジェクトを始める時 には常にこのコマンドを使います。--summary なしで --log-message を指定すると TEXT がログのタイトルと本体の両方 に利用されます。

別名

なし

変更: [A---]

スイッチ

-A, --archive           Override `my-default-archive'.
-d, --dir DIR           Change to DIR first.
-l, --log FILE          Commit with log file FILE.
-s, --summary TEXT      log with summary TEXT plus log-for-merge output
-L, --log-message TEXT  log with TEXT
-S, --setup             Use `make-archive' if necessary.

以下は新しい開発ラインを始める時の典型的なセッションで す。話しを簡単にするために names によるタグづけを選択しまし た。実際のプロジェクトでは特に理由がなければ tagline による タグづけを利用することを推奨します。この場合、各ソースファイ ルの最後か先頭に arch-tag: でタグを埋め込みましょう。詳しく はXXXを見てください。

$ ls
main.c  main.h  tool.c  tools.h
$ tla archive-setup proj2--devo--1.0
* creating category octopus@bluegate.org--2004/proj2
* creating branch octopus@bluegate.org--2004/proj2--devo
* creating version octopus@bluegate.org--2004/proj2--devo--1.0
$ tla init-tree proj2--devo--1.0
$ ls
main.c  main.h  tool.c  tools.h  {arch}
$ tla inventory
P? main.c
P? main.h
P? tool.c
P? tools.h
$ tla id-tagging-method names
method set: names
$ tla inventory
S  main.c
S  main.h
S  tool.c
S  tools.h
$ tla import
* imported octopus@bluegate.org--2004/proj2--devo--1.0
$ tla abrowse
octopus@bluegate.org--2004
  hello
    hello--proj
      hello--proj--1.0
        base-0 .. patch-5

  proj2
    proj2--devo
      proj2--devo--1.0
        base-0

$

CVS対応コマンド

なし


名前

tla commit — チェンジセットベースのリビジョンを保存します

用法

tla commit [options] [[archive]/version] [--
file ...]

説明

DIR(あるいは現在のディレクトリ)にあるプロジェクトツリー の次のリビジョンを作ります。このリビジョンは内部的には直前の リビジョンとの間の差分を示すチェンジセットの形をしています。 自動化された ChangeLog ファイルがある場合チェンジセットの計 算の前にこれらに対する更新がまず発生します。--log-messages が --summary オプションなしに指定された場合 TEXT はログのタ イトルと本体の両方に利用されます。

別名

なし

変更: [A---]

スイッチ

-A, --archive           Override `my-default-archive'
-d, --dir DIR           cd to DIR first
-l, --log FILE          commit with log file FILE
-s, --summary TEXT      log with summary TEXT plus log-for-merge output
-L, --log-message TEXT  log with TEXT plus log-for-merge output
--strict                strict tree-lint
--seal                  create a version-0 revision
--fix                   create a versionfix revision
--out-of-date-ok        commit even if out of date
--file-list FILE        commit only changes to files listed in FILE

ログメッセージをエディタでいちいち書くのが面倒な場合に は -L オプションを使ってコマンドラインでログ内容を指定するこ ともできます:

$ ls
main.c  main.h  tool.c  tools.h  {arch}
$ tla commit -L"add another function to main.c"
M  main.c
* update pristine tree
(octopus@bluegate.org--2004/proj2--devo--1.0--base-0 =>
proj2--devo--1.0--patch-1)
* commited octopus@bluegate.org--2004/proj2--devo--1.0--patch-1
$

CVS対応コマンド

なし


名前

tla get — 指定したリビジョンのプロジェクトツリーを作ります

用法

tla get [options] revision [dir]

説明

REVISION をアーカイブから抽出し、ディレクトリ DIR に新 しいプロジェクトツリーを作ります。DIRが指定されなければ、リ ビジョンの絶対名を持つようなサブディレクトリが現在のディレク トリに作成されます。どのような場合でもプロジェクトツリーとな るディレクトリはあらかじめ存在していてはいけません。

警告

--link オプションを利用する場合には、開発に利用する エディタがコピー・オン・ライト機能を使ったものであることを 確認してください。さもなければリビジョンライブラリが壊れて しまうでしょう。

別名

なし

変更: [-W--]

プロジェクトツリーが新たに作られるので当然書き込みがお こりますが、新規のディレクトリを作りそこに書き込むことが保証 されています。

スイッチ

-A, --archive      Override `my-default-archive'
--cache DIR        cache root for trees with pristines
--no-pristine      don't save a pristine copy
--link             hardlink files to revision library instead of copying
--library          ensure the revision is in a revision library
--sparse           add library entries sparsely (--link, --library)
--non-sparse       add library entries densely (--link, --library)
-s, --silent       no output

hello--proj--1.0 の最新リビジョンを取得します:

$ ls
$ tla get hello--proj--1.0
* from import revision: octopus@bluegate.org--2004/hello--proj--1.0--base-0
* patching for revision: octopus@bluegate.org--2004/hello--proj--1.0--patch-1
* patching for revision: octopus@bluegate.org--2004/hello--proj--1.0--patch-2
* patching for revision: octopus@bluegate.org--2004/hello--proj--1.0--patch-3
* patching for revision: octopus@bluegate.org--2004/hello--proj--1.0--patch-4
* patching for revision: octopus@bluegate.org--2004/hello--proj--1.0--patch-5
* making pristine copy
* tree version set octopus@bluegate.org--2004/hello--proj--1.0
$ ls
hello--proj--1.0--patch-5
$ cd hello--proj--1.0--patch-5/
$ ls
foo.c  {arch}
$

カレントディレクトリに直接取得するのではなく、かならず 新しいサブディレクトリを作ってからリビジョンを展開しているこ とに注意してください。

CVS対応コマンド

なし


名前

tla get-changeset — アーカイブからチェンジセットを抽出します

用法

tla get-changeset [options] revision [dir]

説明

REVISION で指定されたチェンジセットを抽出し DIR で指定 したディレクトリに保存します(あるいは REVISION.patches とい う名前のディレクトリに保存します)。DIR はあらかじめ存在して いてはいけません。

別名

なし

変更: [----]

新しいディレクトリを作って、そこに対する書き込みは発生 します。

スイッチ

-A, --archive  Override `my-default-archive'

tla get と同様ですが、リビジョン全体ではなくチェンジセッ トを取り出してみます:

$ ls
hello--proj--1.0--patch-5
$ tla get-changeset hello--proj--1.0--patch-5
$ ls
hello--proj--1.0--patch-5  hello--proj--1.0--patch-5.patches
$ ls hello--proj--1.0--patch-5.patches/
mod-dirs-index              new-files-archive  original-only-dir-metadata
mod-files-index             orig-dirs-index    patches
modified-only-dir-metadata  orig-files-index   removed-files-archive
$

今度は hello--proj--1.0--patch-5.patches という名前の サブディレクトリを作り、そこにチェンジセットの内容を展開して います。通常の基本的な GNU arch の利用ではチェンジセットを明 示的に扱うことはあまりありません。

CVS対応コマンド

なし


名前

tla lock-revision — アーカイブリビジョンのロック(アンロック)

用法

tla lock-revision [options] revision

説明

REVISION を作成するために必要なロックを獲得します。リ ビジョンは最新のリビジョンの次のリビジョンを指定しなくてはな りませんが、パッチが一つも存在しない場合には無条件に獲得する ことができます。リビジョンが指定されなければ最新のリビジョン がロックされます。(XXX)

このコマンドは非常に低レベルのもので、GNU arch の基本 的な操作ではほとんど利用されることはありません。

別名

なし

変更: [???---]

スイッチ

-A, --archive  Override `my-default-archive'
-u, --unlock   release a lock owned by you
-b, --break    break any existing lock

CVS対応コマンド

なし


名前

tla archive-mirror — アーカイブミラーの更新

用法

tla archive-mirror [options] [from [to] [limit]]

説明

引数を指定しなければ 'my-default-archive'-MIRROR の形 のアーカイブが、'my-default-archive'の内容で更新されます。 [FROM]アーカイブを指定すると [FROM]-MIRROR の形のアーカイブ が[FROM]アーカイブの内容で更新されます。[FROM]と[TO]の両方が 指定されると[TO]アーカイブが[FROM]の内容で更新されます。 LIMIT を指定する場合には、カテゴリ、ブランチ、バージョン、あ るいはリビジョンのいずれかでなければなりません。FROM の中の 指定された部分についてのみ TO にコピーされます。

別名

なし

変更: [A---]

スイッチ

--no-cached        don't copy cached revisions
-s, --summary      print the summary of each patch
--cached-tags      copy only cachedrevs for tags to other archives

CVS対応コマンド

なし

アーカイブコマンド

このグループのコマンドはアーカイブの構成内容をさまざまな形 で表示させるためのものです。いくつかの例外をのぞいて、基本的には 参照のみのコマンドで、アーカイブに対する書き込みは発生しません。 カテゴリ、ブランチ、バージョンなど、GNU arch の名前空間の中間で 利用される名前に関するコマンドがたくさんありますが、これらは新た に作られた tla abrowse コマンドですべて同じことができます。この ような意味で、tla abrowse コマンドが最も良く利用されます。

名前

tla abrowse — アーカイブの閲覧

用法

tla abrowse [options] [limit]

説明

アーカイブの構成をさまざまな角度から表示します。LIMIT を指定するとその部分についてのみ表示されます。LIMIT は完全に 修飾された名前であるか、あるいはアーカイブの名前であるかも知 れません。(XXX 完全に修飾された名前、の説明)

別名

なし

変更: [----]

スイッチ

このコマンドは非常に豊富なスイッチをとります

-A, --archive          Override `my-default-archive'
-r, --reverse          sort revisions from newest to oldest
-s, --summary          print a summary of each patch
-c, --creator          print the creator of each patch
-D, --date             print the date of each patch
-k, --kind             show each revision kind (import, changeset or id)
--desc                 implies -s -c -D -k
--local-merges         list merges from the same archive
--foreign-merges       list merges from other archives
--merges               list all merges
--categories           show category names only
--branches             show branch names only
--versions             show version names only
--omit-empty           omit empty or unchanged-since items
--since SNAP-FILE      show revisions after those listed in SNAP-FILE
--since-limits         limit output to items in the since file
--snap SNAP-FILE       record the highest revisions shown
--force                overwrite an existing snap-file

CVS対応コマンド

なし


名前

tla rbrowse — アーカイブの構成の表示

用法

tla rbrowse [options] [REGULAR_EXPRESSION]

説明

アーカイブの構成を表示します。指定されたアーカイブのカ テゴリ、ブランチ、リビジョンが表示されます。アーカイブが指定 されなければ 'my-default-archive' が利用されます。引数を世紀 表現で指定することに注意してください。

別名

なし

変更: [----]

スイッチ

-a, --search-all  Search all archives
-A, --archive     Use [archive] instead of default

CVS対応コマンド

なし


名前

tla categories — カテゴリの一覧表示

用法

tla categories [options] [archive]

説明

アーカイブ中のカテゴリの一覧を表示します。このコマンド は過去互換性のためにのみ存在しています。tla abrowse を利用し てください。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'

CVS対応コマンド

なし


名前

tla branches — ブランチの一覧表示

用法

tla branches [options] [category]

説明

カテゴリにあるブランチを一覧表示します。このコマンドは 過去互換性のためだけに存在しています。かわりに tla abrowse を利用してください。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'

CVS対応コマンド

なし


名前

tla versions — バージョンの一覧表示

用法

tla versions [options] [branch]

説明

ブランチにあるバージョンを一覧表示します。このコマンド は過去互換性のためにのみ存在しています。tla abrowse コマンド を利用するようにしてください。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'
-r, --reverse  sort from newest to oldest

CVS対応コマンド

なし


名前

tla revisions — アーカイブバージョン中のリビジョンの一覧表示

用法

tla revisions [options] [version]

説明

アーカイブバージョン中のリビジョンの一覧を表示します。 通常このリストは古いほうから新しい方に無かって表示されますが -r(--reverse)オプションで変更することもできます。オプション でパッチ(XXX)を指定すると、もしそのようなパッチが存在してい ればそれについてのみ表示されます。パッチが存在しなければ終了 コード 1 で異常終了します。-r(--reverse)フラグはこのパッチ引 数に影響を与えません。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'
-r, --reverse  sort from newest to oldest
-f, --full     list fully qualified names
-s, --summary  print a summary of each patch
-c, --creator  print the creator of each patch
-D, --date     print the date of each patch

CVS対応コマンド

なし


名前

tla ancestry — リビジョンのバージョン間履歴の表示

用法

tla ancestry [options] [revision]

説明

リビジョンのアーカイブバージョンをまたいだ履歴を表示し ます。あるアーカイブバージョンが別のアーカイブバージョンを元 にして tla tag コマンドで作られた場合、この新しい方のアーカ イブバージョン中のリビジョンは、自分が属しているアーカイブバー ジョンを越えた履歴を持つことになります。この履歴は tla revisions コマンドだけでは表示することができません。tla ancestry コマンドはこの障壁を越えて過去を表示します。

ancestry コマンドは現存しているアーカイブについてのみ 過去に遡れることに注意してください。たとえば A0/C0--B0--V0 -> A1/C1--B1--V1 -> A2/C2--B2--V2 という形で順次タグづけされ たアーカイブバージョンががあり、A2/C2--B2--V2--R というリビ ジョンが最新リビジョンであるとします。ところが A0/C0--B0--V0 にはなんらかの形ですでにアクセス不能になっているとします。こ の場合 tla ancestry は、A1/C1--B1--V1 までの履歴しか表示でき ません。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'
-d, --dir DIR  cd to DIR first
-m, --merges   show merges into this development line
-r, --reverse  list oldest to newest
-s, --summary  print a summary of each patch
-c, --creator  print the creator of each patch
-D, --date     print the date of each patch

CVS対応コマンド

なし


名前

tla ancestry-graph — リビジョンのバージョン間履歴の表示

用法

tla ancestry-graph [options] [revision]

説明

tla ancestry と同じ目的のために存在しますが、別の形式 で表示します。種に歴史的な理由で残されています。

別名

なし

変更: [----]

スイッチ

-A, --archive    Override `my-default-archive'
-d, --dir DIR    cd to DIR first
-m, --merges     show merges into this development line
-r, --reverse    list oldest to newest
-i, --immediate  show only the immediate ancestor
-p, --previous   show the (namespace) previous revision

CVS対応コマンド

なし


名前

tla cat-archive-log — アーカイブログエントリ内容の表示

用法

tla cat-archive-log [options] revision

説明

アーカイブ中の指定したリビジョンのログメッセージ内容を 表示します。プロジェクトツリーではなく、アーカイブから取得す ることに注意してください。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'
--headers      show only log headers

CVS対応コマンド

なし


名前

tla cacherev — アーカイブに完全なソースツリーをキャッシュする

用法

tla cacherev [options] [revision]

説明

アーカイブ中の指定リビジョンの完全なコピーをキャッシュ します。これはそれ以降のリビジョンに対する tla get コマンド を高速化する意味があります。リビジョンを指定しなくてもプロジェ クトツリー中で実行すればそのツリーのデフォルトバージョンにあ る最新リビジョンがキャッシュされます。

別名

なし

変更: [A---]

スイッチ

-A, --archive    Override `my-default-archive'
--cache DIR      cache root for trees with pristines

CVS対応コマンド

なし


名前

tla cachedrevs — アーカイブ中のキャッシュされたリビジョン一覧

用法

tla cachedrevs [options] [version]

説明

アーカイブバージョン VERSION の、どのリビジョンがキャッ シュされているかを表示します。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'

CVS対応コマンド

なし


名前

tla uncacherev — アーカイブ中のリビジョンキャッシュを削除します

用法

tla uncacherev [options] revision [dir]

説明

アーカイブからリビジョンキャッシュを削除します。 REVISION が指定されなくともプロジェクトツリー中で実行されれ ばそのツリーのデフォルトバージョンにある最新リビジョンに対し て処理がおこります。

別名

なし

変更: [A---]

スイッチ

-A, --archive  Override `my-default-archive'

CVS対応コマンド

なし


名前

tla archive-meta-info — アーカイブ中のメタ情報の表示

用法

tla archive-meta-info

説明

アーカイブ中のメタ情報の内容を表示します。例えば:

$ tla archive-meta-info name

は、デフォルトアーカイブの公式な名前を表示します。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'

CVS対応コマンド

なし


名前

tla archive-snapshot — アーカイブスナップショットの更新

用法

tla archive-snapshot [options] dir [limit]

説明

DIR ディレクトリを現在のアーカイブスナップショットで更 新します。LIMIT を指定すると、その部分についてのみ更新します。 アーカイブスナップショットは、アーカイブ名、カテゴリ名、ブラ ンチ名、バージョン名がこの順序で階層化されたディレクトリと、 それぞれのディレクトリにディレクトリ.add という名前のゼロバ イトファイルを含んだ形のネストしたディレクトリです。さらに最 後のバージョンディレクトリ中にはそのバージョンに含まれるリビ ジョン名.add の形のファイルがすべて含まれます。リビジョン名. addのファイルの内容だけは腔ではなく、それぞれのリビジョンの パッチログになります。具体的には以下のような形になります:

$ tla archive-snapshot .
$ find .
./octopus@bluegate.org--2004
./octopus@bluegate.org--2004/a
./octopus@bluegate.org--2004/a.added
./octopus@bluegate.org--2004/a/a--b
./octopus@bluegate.org--2004/a/a--b.added
./octopus@bluegate.org--2004/a/a--b/a--b--c
./octopus@bluegate.org--2004/a/a--b/a--b--c.added
./octopus@bluegate.org--2004/a/a--b/a--b--c/a--b--c--base-0.added
./octopus@bluegate.org--2004/a/a--b/a--b--c/a--b--c--patch-1.added
…

このコマンドは make コマンドのような外部ツールと連係 して、アーカイブへの新規追加されたアイテムに対して一度だけの イベントを発生させるために利用されます。

別名

なし

変更: [----]

スナップショットをとるために指定したディレクトリには書 き込みが発生します。

スイッチ

-A, --archive  Override `my-default-archive'

CVS対応コマンド

なし


名前

tla archive-version — アーカイブ中のアーカイブバージョン表示

用法

tla archive-version [options]

説明

GNU arch アーカイブのアーカイブ識別子を表示します。

注意

ここでアーカイブバージョン、と言っているのは A/C--B--Vのようなものではなく、アーカイブそのものの形式の ことです。アーカイブは今後の GNU arch の拡張によりそれまで 以上に豊富な機能や、最適化される可能性、下位互換性について の考慮が必要になってくる可能畝があります。このためアーカイ ブ作成時にはこのアーカイブの識別子が内部情報として埋め込ま れます。tla archive-version はこの識別子を表示するものです。 識別子によって条件分岐するようなプログラムは、アーカイブの 形式や能力が変化した場合でも下位互換性を失わずに実行するこ とができるようになるでしょう。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'

CVS対応コマンド

なし


名前

tla archive-fixup — アーカイブ中の補助ファイルの修復

用法

tla archive-fixup [options]

説明

このコマンドはアーカイブを正常な状態に復帰させるための 包括的な修復のために用意されたコマンドです。現時点ではこの唯 一の機能はアーカイブにある .listing ファイルを修復することだ けです。

別名

なし

変更: [A---]

スイッチ

-A, --archive  Override `my-default-archive'

CVS対応コマンド

なし

パッチログコマンド

このグループは、二つの分岐した開発ライン間でマージする時に 重要になる「パッチログ」というデータ構造を扱うための コマンド群です。マージの際にパッチログを考慮することによって一度 マージしたチェンジセットをもう一度マージしてしまう、いわゆる重複 マージ問題を解決することができます。GNU arch のような分散型のバー ジョン管理システムではさまざまな分岐関係を経由して、同じチェンジ セットが別の道筋で再び現れることがあるので、パッチログは重要なデー タになります。このグループのコマンドはプロジェクトツリーに対する 書き込みを発生するものもありますが、アーカイブに対する書き込みを するものはありません。このためプロジェクトツリーの最後のコミット 後の変更点さえ保存しておけば[19]、実験的に実行してもアーカイブが おかしな状態になることはありません。

名前

tla make-log — 次のログファイルの用意

用法

tla make-log [options] [version]

説明

DIR にあるプロジェクトツリーのルートに必要に応じてログ ファイルを作ります。このログファイルは VERSION 用のものです。 作成されたログファイルの名称は標準出力に表示されます。

ティップ

ログファイルの名称はバージョン管理対象となるファイル 名と重ならないように、'+'文字で始まる特殊な長いものが利用 されます。このログファイルを編集する場合、vi のような一部 のエディタではこのファイルをファイル名とは認識できず、オプ ションと解釈してしまいます。vi ++ログファイル名 のかわりに vi ./++ログファイル名 のように先頭に './' を付加することで 回避できるエディタもあるようです。詳しくはそれぞれのエディ タのマニュアルを参照してください。

別名

なし

変更: [-W--]

パッチログファイルが作成されますがプロジェクトツリー内 の既存のファイルには一切書き込みは発生しません。またパッチロ グファイルは常に削除可能です。削除によってプロジェクトツリー の状態が不整合を起こすことはありません。

スイッチ

-A, --archive  Override `my-default-archive'
-d, --dir DIR  cd to DIR first

CVS対応コマンド

なし


名前

tla log-versions — プロジェクトツリー中のパッチログバージョンの表示

用法

tla log-versions [options]

説明

DIR または現在のディレクトリに存在しているプロジェクト ツリーはアーカイブバージョンごとに分類されたパッチログを持っ ています。このコマンドを使うとアーカイブバージョンの一覧を表 示することができます。

このアーカイブバージョンは大きく二つに分類されます。一 つはプロジェクトツリー自身のデフォルトアーカイブバージョン —tla tree-version で表示されます—と、その祖先の バージョン、もう一つはそれ以外のアーカイブバージョンです。前 者は tla commit コマンドなどによって自分で追加してきたパッチ ログが保存されている場所で、後者は他の人のチェンジセットを tla replay、tla update、tla star-merge などのコマンドにより 取り込んだ結果[20]保持しているパッチログが保存されている場所 です。

別名

なし

変更: [----]

スイッチ

-d, --dir DIR            cd to DIR first
-a, --archive ARCHIVE    list only logs for ARCHIVE
-c, --category CATEGORY  list only logs for CATEGORY
-b, --branch BRANCH      list only logs for BRANCH
-v, --vsn VERSION        list only logs for VERSION
-r, --reverse            reverse the sort order

CVS対応コマンド

なし



[20] これをチェリーピックといいます。


名前

tla add-log-version — プロジェクトツリーに対するパッチログ用のバージョ ン領域の追加

用法

tla add-log-version [options]
[archive]/version

説明

DIR または現在のディレクトリにあるプロジェクトツリーに、 VERSION 用のパッチログ保存領域を作ります。初期状態ではこの領 域は腔になります。プロジェクトツリーのパッチログは、そのパッ チログのアーカイブバージョンにツリーを追加したり、そのアーカ イブバージョンからのチェンジセットで更新する場合には常に必要 になります。プロジェクトツリーに記録されるバージョンは完全な アーカイブバージョン名で記録されることに注意してください。つ まり、A/C--B--V の形です。

別名

なし

変更: [-W--]

スイッチ

-A, --archive  Override `my-default-archive'
-d, --dir DIR  cd to DIR first

CVS対応コマンド

なし


名前

tla remove-log-version — プロジェクトツリーからのパッチログバージョンの削 除

用法

tla remove-log-version [options] [archive]/version

説明

DIR または現在のディレクトリにあるプロジェクトツリーか ら VERSION に関するパッチログをすべて削除します。このコマン ドは注意して利用してください。プロジェクトツリーからあるリビ ジョンの履歴を消してしまいます。

別名

なし

変更: [-W--]

スイッチ

-A, --archive  Override `my-default-archive'
-d, --dir DIR  cd to DIR first

CVS対応コマンド

なし


名前

tla logs — プロジェクトツリー中の特定のバージョンにあるパッ チログ一覧

用法

tla logs [options] [[archive]/version ...]

説明

VERSION から DIR または現在のディレクトリにあるプロジェ クトツリーに適用されたパッチを一覧表示します。

別名

なし

変更: [----]

スイッチ

-A, --archive         Override `my-default-archive'
-d, --dir DIR         cd to DIR first
-r, --reverse         sort from newest to oldest
-s, --summary         print the summary of each patch
-c, --creator         print the creator of each patch
-D, --date            print the date of each patch
--local-merges        list merges from the same archive
--foreign-merges      list merges from other archives
--merges              list all merges
-f, --full            print full patch level names

CVS対応コマンド

なし


名前

tla cat-log — プロジェクトツリー中のパッチログの内容表示

用法

tla cat-log [options] revision-spec

説明

プロジェクトツリー内にある指定のリビジョンのパッチログ を抽出しその内容を表示します。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'
-d, --dir DIR  cd to DIR first

CVS対応コマンド

なし


名前

tla changelog — パッチログの内容による ChangeLog の生成

用法

tla changelog [options] [[archive]/version]

説明

DIR または現在のディレクトリにあるプロジェクトツリーの VERSION用 ChangeLog を生成します。

別名

なし

変更: [----]

スイッチ

-A, --archive               Override `my-default-archive'
-d, --dir DIR               cd to DIR first
--no-files                  exclude file lists from ChangeLog
--untagged                  don't implicitly tag the output file
--new-entry PATCH,FILE      make FILE the first (top) entry
                              for patch level PATCH

CVS対応コマンド

なし


名前

tla log-for-merge — マージ用ログエントリの生成

用法

tla log-for-merge [options] [[archive]/version]

説明

VERSION へのマージを記述するログエントリの本体を生成し ます。アーカイブ、プロジェクトツリー、いずれに対しても書き込 みは発生しません。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'
-d, --dir DIR  cd to DIR first
-r, --reverse  sort from newest to oldest

CVS対応コマンド

なし


名前

tla merges — 二つの分岐がマージされた場所の報告

用法

tla merges [options] INTO [FROM]

説明

パッチレベル名(XXX)のペアを一覧表示します。(XXX):

INTO-RVN  FROM-RVN

これは INTO のパッチレベル INTO-RVN でログエントリ FROM-RVNが追加されたことを示しています。FROM はブランチ名 (XXX)、バージョン名(XXX)、またはリビジョン名(XXX)のいずれか です。ブランチ名またはバージョン名の場合、そのブランチまたは バージョンからのすべてのマージを報告します。リビジョン名の場 合には指定したリビジョンのマージポイントのみが表示されます。 出力は最初のカラムのパッチレベルの順序でソートされます。FROM がリビジョン名でないかぎり完全な名前で表示されます。FROM が リビジョンである場合には明示的に --full オプションを指定すれ ばそうなります。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'
-d, --dir DIR  cd to DIR first
-r, --reverse  sort from newest to oldest
-f, --full     print full patch level names

CVS対応コマンド

なし


名前

tla new-merges — バージョンに存在しないツリー中のパッチ一覧

用法

tla new-merges [options] [[archive]/version]

説明

DIR にあるプロジェクトツリーに存在し、VERSION にはまだ マージされていないすべてのパッチログエントリを表示します。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'
-d, --dir DIR  cd to DIR first
-r, --reverse  sort from newest to oldest

CVS対応コマンド

なし

マルチプロジェクト設定用コマンド

GNU arch には複数のプロジェクトを組み合わせて一つのまとまっ た大きなプロジェクトを構成する機能があります。これをマルチプロジェ クト機能と言います。たとえば tla や、pika と呼ばれる schema の方 言もこのようなマルチプロジェクトとして管理されています。両方とも hackerlab というライブラリが必要なので、これが一つのバージョンを 構成し、tla も pika もマルチプロジェクトの構成要素の一つとしてこ れを利用しています。

名前

tla build-config — マルチプロジェクト設定環境の構築

用法

tla build-config [options] config

説明

指定した設定環境を実際に構築します。"tla cat-config -H"も参照してください。

別名

なし

変更: [-W--]

構築によりいくつかのプロジェクトツリーが作成されますが いずれも新規ディレクトリに対してです。

スイッチ

-d, --dir DIR       cd to DIR first
--no-pristines      don't create pristine copies
--link              hardlink files to revision library instead of
-copying
--library           ensure revisions are in the revision library
--sparse            add library entries sparsely (--link, --library)
-r, --release-id    overwrite ./=RELEASE-ID for this config

CVS対応コマンド

なし


名前

tla cat-config — マルチプロジェクト設定環境情報の表示

用法

tla cat-config [options] config

説明

プロジェクトツリーから指定された設定ファイルを解析して 表示します。設定ファイルはブランク行、"#"で始まるコメント行 を置くことができます。$NAME という名前の設定ファイルはプロジェ クトツリー中の ./configs/$NAME あるいは $NAME として保存それ ます。設定ファイル中で実際に意味のある行はプロジェクトツリー と相対的なパス名とその場所に保存するプロジェクトあるいはリビ ジョンの情報からなります。例えば以下のような行:

./src/arch   lord@emf.net--2003b/arch--devo--1.0

は、この設定を実際に構築した場合、arch--devo--1.0の最 新リビジョンを ./src/arch としてツリー中に作成するような指定 になります。プロジェクトの指定方法はブランチ名、バージョン名、 あるいは特定のリビジョン名になります。(XXX)

--snap オプションは設定されているプロジェクト中のどの リビジョンが実際の構築対象となるかを調べ、その特定のリビジョ ンを指定する形での設定ファイルを表示します。例えば上であげた 例であれば、以下のような出力が得られます:

./src/arch  lord@emf.net--2003b/arch--devo--1.0--patch-21

--output オプションを指定すると、出力内容が実際の新し い構成としてファイルに保存されます。この場合さらに --force オプションを指定すると既存の設定ファイルを上書きすることがで きます。

別名

なし

変更: [----]

スイッチ

-d, --dir DIR     cd to DIR first
-o, --output CFG  write the output as config CFG
-f, --force       overwrite an exiting config (with --output)
-s, --snap        Show current patch levels of subtree packages.

CVS対応コマンド

なし

ブランチとマージに関するコマンド

このグループのコマンドは、ある一つの開発ライン [21]を 二つの開発ラインに分岐したり、そのように分岐された起源を同じくす る開発ライン同士の一部分を相手から取り込んだりするためのコマンド です。このグループのコマンドが書き込む対象は基本的にはプロジェク トツリーです。アーカイブに対する書き込みは例外的なものを除いてあ りません。そのため、コミット前にマージの結果を常に確認することが できます。[22]

名前

tla tag — 継続リビジョンの作成(タグ、あるいは分岐)

用法

tla tag [options] SOURCE-REVISION TAG-VERSION

説明

TAG-VERSION で指定した継続リビジョンを作ります。このリ ビジョンはパッチログエントリが追加されることを除いて SOURCE-REVISION と意味的に同じ内容のリビジョンになります。ロ グエントリを明示的に指定しなければ最小限の情報を持ったログが 自動生成されます。

警告

このコマンドで言うタグ、とは、インベントリタグとは何 の関係もないことに注意してください。両者は別の概念です。混 乱を避けるため、タグのかわりに継続ということばを使うのが良 いでしょう。

別名

なし

変更: [A---]

スイッチ

-A, --archive   Override `my-default-archive'
-l, --log FILE  commit with log file FILE
--seal          create a version-0 revision
--fix           create a versionfix revision

CVS対応コマンド

なし


名前

tla update — アーカイブ済みの最近の修正を反映するためのプロジェ クトツリーの更新

用法

tla update [options] [version/revision]

説明

VERSION(あるいはプロジェクトツリーのデフォルトバージョ ン) の最新リビジョンを取得し、プロジェクトツリーと最新リビジョ ンとの間の差分であるチェンジセットを適用することでプロジェク トツリーを更新します。マージが衝突した場合、警告が表示され新 しいプロジェクトツリーには ".rej"ファイルが残ります。

別名

なし

変更: [-W--]

スイッチ

-A, --archive    Override `my-default-archive'
-d, --dir DIR    Update project tree in DIR (default `.')
-N, --forward    pass the --forward option to `patch'
--dest DEST      Instead of modifying the project tree in-place,
                 make a copy of it to DEST and apply the result to that

CVS対応コマンド

なし


名前

tla replay — プロジェクトツリーに対するチェンジセットの適用

用法

tla replay [options] [version/revision...]

説明

VERSIONまたはプロジェクトツリーのデフォルトバージョン 中の未適用のチェンジセットを順次適用し、最初に衝突が起きた時 点で処理を中止します。複数の VERSION が指定された場合には、 指定した順序で逐次処理をします。VERSION のかわりにひとつ以上 の REVISION が指定された場合にはそれらのみを適用し他のリビジョ ンは適用しません。ここで言うリビジョンは、厳密にはリビジョン 名によって示されるチェンジセットのことです。

--listオプションを指定すると適用するチェンジセットの一 覧をFILE(あるいは '-'を指定するすることで標準入力)から読み込 みます。このファイルの格行は完全なリビジョン名を含んでいなけ ればなりません。マージで衝突が起こった最初のチェンジセットで 処理は中断され、以下の形のファイルが残されます:

表 C.2. replay時に残されるファイル

名前意味
,,replay.conflicts-in衝突を起こしたチェンジセットの名前
,,replay.remaining適用されなかったチェンジセットの一覧

別名

なし

変更: [-W--]

スイッチ

-A, --archive       Override `my-default-archive'
--list FILE         read a list of patches to apply
--new               replay only new patches
--reverse           reverse the named patch
-N, --forward       pass the --forward option to `patch'
-d, --dir DIR       Operate on project tree in DIR (default `.')
--dest DEST         Instead of modifying the project tree in-place,
                    make a copy of it to DEST and apply the result to that
--skip-present      skip patches that contain 1 or more patch logs already in this tree

CVS対応コマンド

なし


名前

tla star-merge — 相互にマージされた開発ライン間でのマージ

用法

tla star-merge [options] [FROM]

説明

プロジェクトツリーに FROM からの変更点をマージしますが、 この際、プロジェクトツリー側の参照基準点をバージョン REFERENCE とみなした上て FROM との間の共通の祖先を考慮します。 REFERENCEを指定しなければプロジェクトツリーのデフォルトバー ジョンが利用されます。FROM が指定されなければ、プロジェクト ツリーのリビジョンが利用されます。このコマンドの目的は、双方 向にマージが起こる可能性のある二つの開発ライン間の変更をマー ジすることです。マージに関する履歴をうまく利用することによっ て'相互マージ'からおこる過剰な衝突を最小限に押えようとします。

処理の詳細を以下に述べます。まず FROM はあるリビジョン を示しています。リビジョンのかわりにバージョンが指定された場 合は、そのバージョンにある最新のリビジョンが指定されたものと 考えます。次に TREE を実際のマージがおこるプロジェクトツリー であるとします。このとき star-merge は REFERENCE と FROM リ ビジョンとの間の「直近の共通祖先」 ANCESTOR を計 算し、それから以下のチェンジセット:

delta (ANCESTOR, FROM)

を、TREE に適用します。つまり ANCESTOR と FROM の差分 を TREE に適用します。

あとは「直近の共通祖先」を定義すれば話しが 終ります。このため更に MAYBE_ANCESTOR_1, MAYBE_ANCESTOR_2, LAST_MERGE_INTO_FROM を補助的に定義します。

MAYBE_ANCESTOR_1 は、TREE と FROM の双方が持っているパッ チログでバージョン REFERENCE に属するもののうち、最も大きな パッチレベルに対応したリビジョンです。言い替えると TREE にす でにマージされた FROM が属するバージョンにあるリビジョンのう ち、REFERENCE に含まれる最後のリビジョンのことです。 MAYBE_ANCESTOR_2 は FROM と REFERENCE の両方にあるパッチログ のうち、REFERENCE 中での最も大きなパッチレベルとして定義され ます。言い替えると、すでに FROM にマージされたリビジョンのう ち、REFERENCE バージョンに属する最後のリビジョンのことです。 MAYBE_ANCESTOR が 空でない場合、これはは FROM のバージョン中 のあるリビジョンで FROM にマージされたはずです。このリビジョ ンを LAST_MERGE_INTO_FROM と言います。 MAYBE_ANCESTOR_1 も MAYBE_ANCESTOR_2 も空であれば star-merge は何もしません。どちらか一方のみが空であれば、もう一方の腔で ない方を ANCESTOR とします。両方共空でない場合は LAST_MERGE_INTO_FROM と MAYBE_ANCESTOR_1 が比較されます(両方 とも FROM のバージョン中のリビジョンであることに注意してくだ さい)。もし MAYBE_ANCESTOR_1 の方が新しければこれを ANCESTOR とします。そうでなければ MAYBE_ANCESTOR_2 を ANCESTOR としま す。

star-merge のアルゴリズムはこのように複雑ですが、利用 するのは簡単です。重要なことは 1. このコマンドはほとんどの場 合にマージ作業をうまくやってくれること、2. マージの結果はプ ロジェクトツリーに反映させるだけでアーカイブへの書き込みはお こらないこと、3. star-merge が何を実行しようとその実行結果は tla changes --diffs コマンドで確認できること、4. 実行結果が 気に入らなければいつでも tla undo で取り消せること、です。マー ジのアルゴリズムについては star-merge の他にもいくつかのアイ ディアが模索されています。

別名

なし

変更: [-W--]

スイッチ

-A, --archive            Override tree archive
-c, --changes OUTPUT     Generate but don't apply the changeset.
-r, --reference VERSION  Set reference version (default: project tree version)
-N, --forward            pass the --forward option to `patch'
-t, --three-way          Perform a 3-way (diff3-style) merge.
-d, --dir DIR            Operate on project tree in DIR (default`.')

CVS対応コマンド

なし


名前

tla apply-delta — 任意の二つのツリー間で計算されたチェンジセットの プロジェクトツリーへの適用

用法

tla apply-delta [options] FROM TO

説明

FROM と TO の間の差分をチェンジセットの形に求め、結果 をDIRまたは現在のディレクトリにあるプロジェクトツリーに適用 します。ここで FROM も TO もプロジェクトツリーに限定されない 一般的なツリーであれば良いことに注意してください。プロジェク トツリーであってももちろんかまいません。終了ステータスは以下 のような意味を持ちます。

表 C.3. 終了ステータスの意味

終了ステータス意味
0チェンジセットの適用時に衝突はなかった
1チェンジセットの適用時に衝突があった
3内部エラー

別名

なし

変更: [-W--]

スイッチ

-A, --archive    Override `my-default-archive'
-N, --forward    pass the --forward option to `patch'
--cache DIR      specify a cache root for pristine copies
-d, --dir DIR    Operate on project tree in DIR (default `.')
--dest DEST      Instead of modifying the project tree in-place,
                 make a copy of it to DEST and apply the result to that

CVS対応コマンド

なし


名前

tla missing — 未適用チェンジセット一覧の表示

用法

tla missing [options] [revision]

説明

VERSION に関して DIR にあるプロジェクトツリーに適用さ れていないチェンジセットの一覧を表示します。DIRが省略される と現在のディレクトリが、VERSION が省略されるとプロジェクトツ リーのデフォルトバージョンが利用されます。--merges を指定す ると、表示されるチェンジセットごとにそのチェンジセットが含ん でいる別のチェンジセットを 2 カラム形式で表示します。例えば:

PATCH-A        PATCH-A
PATCH-A        PATCH-B
PATCH-A        PATCH-C

は PATCH-A が PATCH-B と PATCH-C を含んでいることを示 しています。(どのようなチェンジセットでも、少なくとも自分自 身は必ず含んでいます)。

別名

なし

変更: [----]

スイッチ

-A, --archive       Override `my-default-archive'
-d, --dir DIR       cd to DIR first
-r, --reverse       sort from newest to oldest
-s, --summary       display a summary of each missing patch
-c, --creator       display the creator of each missing patch
-D, --date          display the date of each missing patch
-f, --full          print full revision names
--merges            print a merge list for each missing patch
--skip-present      skip patches that contain 1 or more patch logs already in this tree

CVS対応コマンド

なし


名前

tla join-branch — 指定したバージョン用のプロジェクトツリーの構築

用法

tla join-branch [options] revision/version

説明

REVISION はプロジェクトツリーの祖先の継続(例えばタグ) でなければなりません。このコマンドはプロジェクトツリー中の REVISION のチェンジセットを replay しますが、それはそのブラ ンチのログを追加する効果があります(結果のツリーの祖先にタグ をつけることになります)通常の規約にしたがって、REVISION がバー ジョン名である場合にはそのバージョンの base-0 リビジョンが指 定されたものと考えます。

別名

なし

変更: [-W--]

スイッチ

-A, --archive    Override `my-default-archive'
-d, --dir DIR    Operate on project tree in DIR (default `.')
--dest DEST      Instead of modifying the project tree in-place,
                 make a copy of it to DEST and apply the result to that

CVS対応コマンド

なし


名前

tla sync-tree — 指定したリビジョンを示す形にプロジェクトツリーの パッチログを統合する

用法

tla sync-tree [options] revision

説明

リビジョン REVISION に含まれるパッチログで DIR または 現在のディレクトリにあるプロジェクトツリーに含まれないものを 追加します。実際のマージはおこりません—パッチログ情報 のみが修正されます。

別名

なし

変更: [-W--]

スイッチ

-A, --archive    Override `my-default-archive'
-d, --dir DIR    Operate on project tree in DIR (default `.')
--dest DEST      Instead of modifying the project tree in-place,
                 make a copy of it to DEST and apply the result to that

CVS対応コマンド

なし


名前

tla delta — 二つのツリー間チェンジセットの計算

用法

tla delta [options] TREE-A TREE-B [destdir]

説明

TREE-A と TREE-B の差分であるチェンジセットを計算し、 destdirに保存します。TREE-A 、TREE-B はいずれも任意のツリー であっても、リビジョンツリーであってもかまいません。

例としては:

$ tla delta tla--devo--1.1--patch-6 \
            tla--devo--1.1--patch-8 ,,changes

は、tla--devo--1.1 バージョンから patch-6 と patch-8 のリビジョンを抽出し、両者間のチェンジセットを ,,changes ディ レクトリを新規に作って保存します。

別名

なし

変更: [----]

処理結果のディレクトリには書き込みが発生しますがこのディ レクトリは新規に作成されたものであることが保証されます。

スイッチ

-A, --archive       Override `my-default-archive'
--cache DIR         specify a cache root for pristine copies
--report            output a changeset report
-n, --no-changeset  don't save the delta

CVS対応コマンド

なし

ローカルキャッシュ関連コマンド

プロジェクトツリーに加えた変更点を元に戻したい場合、アーカ イブに対して最後のリビジョンを再ロードする必要がありますが、これ だとアーカイブとプロジェクトツリーは常にネットワークで接続された 状態になければなりません。これではプロジェクトツリーだけを用意し たコンピュータ上でオフライン開発する場合には不便なので、通常最後 のリビジョンをプロジェクトツリー内の {arch} 領域にもう一セット保 存しておきます。このコピーのことをプリスティンコピーと言います。 このグループのコマンドはプリスティンコピーに対する操作です。ここ でのコマンドもアーカイブに対する書き込みは発生しません。また基本 的にはプロジェクトツリーに対する参照のみですが、add-pristine だ けは書き込みが発生します。しかしこの場合でもキャッシ領域に対する 書き込みなので、作業中のデータが変更されることはありません。

名前

tla changes — プロジェクトツリーに加えたローカルな変更点の表示

用法

tla changes [options] [revision] [-- limit...]

説明

DIR または現在のディレクトリにあるプロジェクトツリーの 内容と REVISION との間の差分をパッチ形式で生成し表示します。 バージョンが指定された場合のデフォルトリビジョンはプロジェク トツリーがパッチログを持っている最新のリビジョンです。バージョ ンが省略された場合にはデフォルトバージョンを利用します。

別名

なし

変更: [----]

スイッチ

-A, --archive     Override `my-default-archive'.
-d, --dir DIR     Change to DIR first.
-o, --output DIR  Save changeset in DIR (implies --keep).
-v, --verbose     Verbose changeset report.
-q, --quiet       Suppress progress information
--diffs           Include diffs in the output.
-k, --keep        Don't remove the output directory
                  on termination.

CVS対応コマンド

なし


名前

tla file-diffs — show local changes to a file

用法

tla file-diffs

説明

このコマンドはすでに一度説明しました

別名

なし

変更: [----]

スイッチ

-A, --archive   Override `my-default-archive'
-N, --new-file  Treat missing file as empty

CVS対応コマンド

なし


名前

tla file-find — ファイルのバージョンの検索

用法

tla file-find [options] file [revision]

説明

REVISION のキャッシュコピー中にある FILE に対応したファ イル位置を表示します。バージョンを指定した場合のデフォルトの パッチレベルはそのプロジェクトツリーがパッチを持つ最新のレベ ルになります(XXX)。デフォルトのアーカイブバージョンは 'tla tree-version' で表示されるものになります。

別名

なし

変更: [----]

スイッチ

-A, --archive   Override `my-default-archive'
-N, --new-file  Print missing file as `/dev/null'

CVS対応コマンド

なし


名前

tla pristines — プロジェクトツリー中のプリスティンの一覧

用法

tla pristines [options] [limit]

説明

DIR または現在のディレクトリにあるプロジェクトツリーが キャッシュしているプリスティンリビジョンの一覧を表示します。

別名

なし

変更: [----]

スイッチ

-d, --dir DIR   cd to DIR first
-u, --unlocked  return only unlocked pristines
-l, --locked    return only locked pristines
-r, --reverse   reverse sort order

CVS対応コマンド

なし


名前

tla lock-pristine — プリスティンのロックとアンロック

用法

tla lock-pristine [options] revision

説明

DIR または現在のディレクトリにあるプロジェクトツリーが 持っているリビジョン REVISION のプリスティンにロックします。 これはそのリビジョンが自動的に回収されてしまうのを防ぎます。

別名

なし

変更: [???---]

スイッチ

-A, --archive  Override `my-default-archive'
-d, --dir DIR  cd to DIR first
-u, --unlock   unlock, rather than lock

CVS対応コマンド

なし


名前

tla add-pristine — 特定のプリスティンリビジョンのプロジェクトツリー への追加

用法

tla add-pristine [options] revision

説明

アーカイブから REVISION を抽出し、プリスティンコピーを 作ります。このコピーは DIR または現在のディレクトリにあるプ ロジェクトツリー中に保管されます。

別名

なし

変更: [-W--]

スイッチ

-A, --archive  Override `my-default-archive'
-d, --dir DIR  cd to DIR first

CVS対応コマンド

なし


名前

tla find-pristine — プリスティンリビジョンの検索とパスの表示

用法

tla find-pristine

説明

指定されたリビジョンのプリスティンコピーの場所を表示し ます。

別名

なし

変更: [----]

スイッチ

-A, --archive    Override `my-default-archive'
-d, --dir DIR    cd to DIR first
-u, --unlocked   return only an unlocked pristine
-l, --locked     return only a locked pristine
-t, --tree-only  search this tree only, not siblings
-s, --silent     exit status only

CVS対応コマンド

なし

リビジョンライブラリコマンド

チェンジセット指向の GNU arch には一つの大きな欠点がありま す。それは、特定のリビジョンをアーカイブから高速に取り出すことが できないということです。あるリビジョンを得るためにはそのベースリ ビジョン base-0 に対して、引き続くチェンジセットを適用した結果を 計算しなければなりません。リビジョンの数が増えてベースリビジョン からの距離が通るなるにつれてこの処理には時間がかかるようになるか らです。ここでのコマンドは、リビジョンの取得を高速化するためのリ ビジョンライブラリと呼ばれるキャッシュに関するコマンドです。リビ ジョンライブラリは大きな領域が必要になりそうな気がしますが、実際 には Unix のハードリンクの考え方を利用して効率よくリビジョンデー タ内容を表現しています。

このグループのコマンドは既存のアーカイブに対してキャッシュ を計算することが主ですので、もとのアーカイブに対しての書き込みは 発生しません。またプロジェクトツリーに対しても同様です。リビジョ ンライブラリは指定した専用のリビジョンライブラリ用のディレクトリ に保存されるので、その領域の配下には書き込みがおこります。

名前

tla my-revision-library — 自分のリビジョンライブラリパスの表示と設定

用法

tla my-revision-library [options] [dir]

説明

引数がなくて -d オプションも指定されていない場合には自 分のリビジョンライブラリのパスを表示します。引数がある場合 DIRを自分のリビジョンライブラリへのパスとして ~/.arch-params/=revision-library に保存します。-d (--delete) オプションを指定し引数がない場合は~/.arch-paramsに記録されて いるリビジョンライブラリパスを削除します。リビジョンライブラ リが設定されなかった場合、プログラムは終了ステータス 1 を返 し -s (--silent)オプションが指定されない限りエラーメッセージ を表示します。

別名

なし

変更: [--C-]

スイッチ

-e, --errname      specify program name for errors
-d, --delete       unspecify your revision library
-s, --silent       suppress reassuring messages
--search           use the full search path
--add              use the full add path
--search-only      use the search-only path
--add-only         use the add-only path
--first            prepend to the path if setting (default appends)

CVS対応コマンド

なし


名前

tla library-config — リビジョンライブラリのパラメータ設定

用法

tla library-config [options] library-dir

説明

リビジョンライブラリに対するさまざまなパラメータを表示 または設定します。現時点では greedy と sparse というブール値 があります。両者は独立して設定できます。greedy を有効にする と、あるリビジョンのプリスティンコピーが作られた時には常にラ イブラリにもそのリビジョンを自動的に追加します。こうしておけ ばライブラリにたいして明示的にリビジョン追加しなくても一度 tla getなどで取得したリビジョンは次回からは高速に取得するこ とができるようになります。欠点はライブラリの領域が知らないう ちに大きくなってしまうことです。

sparse オプションは、あるリビジョンがライブラリに追加 された時にそのリビジョンを作る過程で得られたリビジョンも一緒 にライブラリに追加するかどうかを制御します。sparse を有効に すると途中のリビジョンは追加されず、指定したリビジョンだけが ライブラリに登録されます。sparse をつけないと中間のリビジョ ンも自動的に追加されます。たとえば C--B--V--base-0 からはじ まるバージョンの最新リビジョンが C--B--V--patch-5 であるとし ます。sparse オプションをつけずに tla library-add C--B--V--patch-5を実行すると C--B--V--base-0 .. C--B--V--patch-4までのすべてのリビジョンもライブラリに登 録されます。sparse オプションをつけると C--B--V--patch-5 の みが追加されます。

greedy と sparse オプションの on/off の組み合わせをう まく選ぶことで、ライブラリ領域と、リビジョン取得時の時間効率 を最適にすることができます。

別名

なし

変更: [---L]

スイッチ

--greedy          make the library greedy
--non-greedy      make the library not greedy
--sparse          make the library sparse (by default)
--non-sparse      make the library not sparse (by default)

CVS対応コマンド

なし


名前

tla library-find — リビジョンライブラリ中のリビジョン位置の検索と表示

用法

tla library-find [options] revision

説明

自分のリビジョンライブラリ中で REVISION を検索しそのパ スを表示します。リビジョンを指定しなければ--silient オプショ ンを指定しないかぎりエラーメッセージを表示し、ゼロではない終 了ステータスで終了します。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'
-e, --errname  specify program name for errors
-s, --silent   suppress reassuring messages

CVS対応コマンド

なし


名前

tla library-add — リビジョンライブラリへのリビジョンの追加

用法

tla library-add [options] revision

説明

自分のリビジョンライブラリに REVISION を追加します。す でに追加されている場合には何もせずに終了ステータスゼロでプロ グラムを終了します。

別名

なし

変更: [---L]

スイッチ

-A, --archive         Override `my-default-archive'
-s, --sparse          Don't fill in gaps in the library.
--non-sparse          Fill in gaps in the library.
-L, --library LIB     specify which library to add to
--for-links PATH      require a lib on the same device as PATH

CVS対応コマンド

なし


名前

tla library-remove — リビジョンライブラリからのリビジョンの削除

用法

tla library-remove [options] revision

説明

自分のリビジョンライブラリから REVISION を削除します。 そのリビジョンがライブラリ中に存在しない場合にはエラーメッセー ジを表示してゼロ以外のステータスで終了します。

別名

なし

変更: [---L]

スイッチ

-A, --archive  Override `my-default-archive'

CVS対応コマンド

なし


名前

tla library-archives — リビジョンライブラリ中のアーカイブ一覧

用法

tla library-archives [options]

説明

リビジョンライブラリ中のすべてのアーカイブを一覧表示し ます。

別名

なし

変更: [----]

スイッチ

なし

CVS対応コマンド

なし


名前

tla library-categories — リビジョンライブラリ中のカテゴリの一覧

用法

tla library-categories [options] [archive]

説明

リビジョンライブラリ中の指定アーカイブにあるすべてのカ テゴリを表示します。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'

CVS対応コマンド

なし


名前

tla library-branches — ライブラリカテゴリ中のブランチの一覧

用法

tla library-branches [options] [category]

説明

リビジョンライブラリ中の CATEGORY にあるすべてのブラン チを表示します。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'

CVS対応コマンド

なし


名前

tla library-versions — ライブラリブランチにあるバージョンの一覧表示

用法

tla library-versions [options] [branch]

説明

リビジョンライブラリに登録されている特定の archive/branch にあるすべてのバージョンを表示します。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'
-r, --reverse  sort from newest to oldest

CVS対応コマンド

なし


名前

tla library-revisions — ライブラリバージョン中のリビジョンの一覧

用法

tla library-revisions [options] [version]

説明

リビジョンライブラリに登録された特定の archive/version にあるすべてのリビジョンを表示します。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'
-r, --reverse  sort from newest to oldest
-f, --full     list fully qualified names
-s, --summary  print a summary of each patch
-c, --creator  print the creator of each patch
-D, --date     print the date of each patch

CVS対応コマンド

なし


名前

tla library-log — リビジョンライブラリからのログメッセージの表示

用法

tla library-log [options] revision

説明

ライブラリ中の REVISION のもつログメッセージを表示しま す。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'
-s, --silent   suppress reassuring messages

CVS対応コマンド

なし


名前

tla library-file — リビジョンライブラリ中でのファイル検索

用法

tla library-file [options] file revision

説明

リビジョンライブラリの REVISION で FILE を検索しそのパ スを表示します。リビジョン、あるいはファイルが存在しなければ エラーメッセージを表示してゼロではないステータスを返します。

別名

なし

変更: [----]

スイッチ

-A, --archive  Override `my-default-archive'
--id           interpret FILE as an inventory id
--this         interpret FILE as a file within a project tree

CVS対応コマンド

なし

公開用リビジョンコマンド

GNU arch はアーカイブ名とアーカイブ位置とを独立に定義しま す。これは論理的なアーカイブ名を変更せずにアーカイブ位置のみを変 更することで別の物理的なアーカイブにアクセスできるようにするため です。これはたとえば、あるマスターアーカイブが現在ダウンしていて、 そのかわりにミラーサイトにアクセスするような場合に役立ちます。アー カイブ位置を変更するためのコマンドを使って[23]アーカイブ位置のみを変更すれば、 アーカイブ名を含む、tla を内部で呼び出すような既存のスクリプトに は一切修正を加えることなく作業を継続できます。

アーカイブ位置からアーカイブ名を自動的に求め登録してくれる 仕組みがあると便利です。tla grab はこれを実行してくれます。

名前

tla grab — 公開用リビジョンの取得

用法

tla grab [options] location

説明

公開用リビジョンを取得します。GNU arch でリモートアー カイブにある特定のリビジョンを取得する場合には、以下の手続き を踏む必要があります。1. tla register-archive コマンドでアー カイブ名とアーカイブ位置を結び付ける。2. tla get コマンドで 必要なアーカイブリビジョンを指定する。tla grab は以下のよう な形のファイルにアクセスし、この処理を簡略化します:

Archive-Name: tez@kamihira.com--2004s
Archive-Location: http://arch.bluegate.org/{archives}/tez@kamihira.com--2004s
Target-Revision: ViewARCH--devo--0.0.8
Target-Directory: ViewARCH

上記のような形のファイルを、 http://arch.bluegate.org/grabs/ViewARCH--devo--0.0.8 のような場所に置いておくと、以下のコマンドで ViewARCH--devo--0.0.8 の最新リビジョンを取得することができま す。

$ tla grab http://arch.bluegate.org/grabs/ViewARCH--devo--0.0.8

別名

なし

変更: [-WC-]

書き込みが発生するプロジェクトツリーは新規に作成された ものであることが保証されています。

スイッチ

なし

CVS対応コマンド

なし

スクリプト支援コマンド

GNU arch のアーカイブは複雑な名前空間を持つので、A/C--B--V のような文字列からアーカイブ名、カテゴリ名、ブランチ名、バージョ ン名を抽出したり、そもそも指定された文字列がこの形式になっている かどうかをチェックが必要となる場面が現れます。GNU arch の tla コ マンドを呼び出し結果を利用する高レベルのスクリプトを支援するため にこのアーカイブ名の解析をするためのコマンドを用意しています。こ のグループのコマンドはアーカイブ領域、プロジェクトツリー領域いず れにたいしても書き込みをしません。

名前

tla parse-package-name — パッケージ名称の解析

用法

tla parse-package-name [options] name

説明

パッケージ名 name を解析します。パッケージ名とは A/C--B--Vまたはその一部のような形をした文字列のことです。 (XXX)

別名

なし

変更: [----]

スイッチ

-A, --archive          Override `my-default-archive'
-a, --arch             print the archive name
--non-arch             print the non-archive part of the name
-c, --category         print the category name
-b, --branch           print the branch name
-p, --package          print the package name
-v, --vsn              print the version id
--package-version      print the category--branch--version
-l, --lvl              print the patch level
--patch-level          synonym for --lvl

CVS対応コマンド

なし


名前

tla valid-package-name — パッケージ名称の妥当性の検証

用法

tla valid-package-name [options] name

説明

パッケージ名 name の妥当性を検証します。デフォルトでは ベース名またはベース名とブランチ名をつなげた ものです。オプション -v と -l は -b を打ち消します。逆も言え ます。-l は -v を暗黙に含みます。エラー名が -e または --errname で指定された場合にはエラーを起こした名前が標準出力 に表示されます。そうでなければ終了ステータスのみが表示されま す。デフォルトでは妥当性チェックは厳密に行われます。たとえば -b は正しいベース名であるかどうかを確認し、ブランチ名やバー ジョン番号を認めません。-t を指定するとより具体的な名前を認 めます。たとえば -b はブランチ名、バージョン名、パッチレベル のいずれも正しいものとして認めます。

ベース名の説明をする必要がある。

別名

なし

変更: [----]

スイッチ

-e, --errname      specify program name for errors
--archive          require and explicit archive
--no-archive       prohibit and explicit archive
-c, --category     require a category
-p, --package      require category, permit branch
-v, --vsn          require a version number
-l, --patch-level  require a patch level
--lvl              synonym for --patch-level
-t, --tolerant     tolerate more specific names

CVS対応コマンド

なし



[19] tla undo を利用すれ ばよいのでした

[20] これをチェリーピックといいます。

[21] 開発ラインとはあるバージョンのことを言います。 A/C--B--V のようなものを思い浮かべてください

[22] tla changes --diffs を利用します

[23] tla register-archive

付録 D. Copyright

		GNU Free Documentation License
		  Version 1.2, November 2002


 Copyright (C) 2000,2001,2002  Free Software Foundation, Inc.
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.


0. PREAMBLE

The purpose of this License is to make a manual, textbook, or other
functional and useful document "free" in the sense of freedom: to
assure everyone the effective freedom to copy and redistribute it,
with or without modifying it, either commercially or noncommercially.
Secondarily, this License preserves for the author and publisher a way
to get credit for their work, while not being considered responsible
for modifications made by others.

This License is a kind of "copyleft", which means that derivative
works of the document must themselves be free in the same sense.  It
complements the GNU General Public License, which is a copyleft
license designed for free software.

We have designed this License in order to use it for manuals for free
software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the
software does.  But this License is not limited to software manuals;
it can be used for any textual work, regardless of subject matter or
whether it is published as a printed book.  We recommend this License
principally for works whose purpose is instruction or reference.


1. APPLICABILITY AND DEFINITIONS

This License applies to any manual or other work, in any medium, that
contains a notice placed by the copyright holder saying it can be
distributed under the terms of this License.  Such a notice grants a
world-wide, royalty-free license, unlimited in duration, to use that
work under the conditions stated herein.  The "Document", below,
refers to any such manual or work.  Any member of the public is a
licensee, and is addressed as "you".  You accept the license if you
copy, modify or distribute the work in a way requiring permission
under copyright law.

A "Modified Version" of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.

A "Secondary Section" is a named appendix or a front-matter section of
the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall subject
(or to related matters) and contains nothing that could fall directly
within that overall subject.  (Thus, if the Document is in part a
textbook of mathematics, a Secondary Section may not explain any
mathematics.)  The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding
them.

The "Invariant Sections" are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
that says that the Document is released under this License.  If a
section does not fit the above definition of Secondary then it is not
allowed to be designated as Invariant.  The Document may contain zero
Invariant Sections.  If the Document does not identify any Invariant
Sections then there are none.

The "Cover Texts" are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License.  A Front-Cover Text may
be at most 5 words, and a Back-Cover Text may be at most 25 words.

A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
general public, that is suitable for revising the document
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters.  A copy made in an otherwise Transparent file
format whose markup, or absence of markup, has been arranged to thwart
or discourage subsequent modification by readers is not Transparent.
An image format is not Transparent if used for any substantial amount
of text.  A copy that is not "Transparent" is called "Opaque".

Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML
or XML using a publicly available DTD, and standard-conforming simple
HTML, PostScript or PDF designed for human modification.  Examples of
transparent image formats include PNG, XCF and JPG.  Opaque formats
include proprietary formats that can be read and edited only by
proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the
machine-generated HTML, PostScript or PDF produced by some word
processors for output purposes only.

The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page.  For works in
formats which do not have any title page as such, "Title Page" means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.

A section "Entitled XYZ" means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following
text that translates XYZ in another language.  (Here XYZ stands for a
specific section name mentioned below, such as "Acknowledgements",
"Dedications", "Endorsements", or "History".)  To "Preserve the Title"
of such a section when you modify the Document means that it remains a
section "Entitled XYZ" according to this definition.

The Document may include Warranty Disclaimers next to the notice which
states that this License applies to the Document.  These Warranty
Disclaimers are considered to be included by reference in this
License, but only as regards disclaiming warranties: any other
implication that these Warranty Disclaimers may have is void and has
no effect on the meaning of this License.


2. VERBATIM COPYING

You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies
to the Document are reproduced in all copies, and that you add no other
conditions whatsoever to those of this License.  You may not use
technical measures to obstruct or control the reading or further
copying of the copies you make or distribute.  However, you may accept
compensation in exchange for copies.  If you distribute a large enough
number of copies you must also follow the conditions in section 3.

You may also lend copies, under the same conditions stated above, and
you may publicly display copies.


3. COPYING IN QUANTITY

If you publish printed copies (or copies in media that commonly have
printed covers) of the Document, numbering more than 100, and the
Document's license notice requires Cover Texts, you must enclose the
copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover.  Both covers must also clearly and legibly identify
you as the publisher of these copies.  The front cover must present
the full title with all words of the title equally prominent and
visible.  You may add other material on the covers in addition.
Copying with changes limited to the covers, as long as they preserve
the title of the Document and satisfy these conditions, can be treated
as verbatim copying in other respects.

If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto adjacent
pages.

If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
a computer-network location from which the general network-using
public has access to download using public-standard network protocols
a complete Transparent copy of the Document, free of added material.
If you use the latter option, you must take reasonably prudent steps,
when you begin distribution of Opaque copies in quantity, to ensure
that this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you distribute an
Opaque copy (directly or through your agents or retailers) of that
edition to the public.

It is requested, but not required, that you contact the authors of the
Document well before redistributing any large number of copies, to give
them a chance to provide you with an updated version of the Document.


4. MODIFICATIONS

You may copy and distribute a Modified Version of the Document under
the conditions of sections 2 and 3 above, provided that you release
the Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution
and modification of the Modified Version to whoever possesses a copy
of it.  In addition, you must do these things in the Modified Version:

A. Use in the Title Page (and on the covers, if any) a title distinct
   from that of the Document, and from those of previous versions
   (which should, if there were any, be listed in the History section
   of the Document).  You may use the same title as a previous version
   if the original publisher of that version gives permission.
B. List on the Title Page, as authors, one or more persons or entities
   responsible for authorship of the modifications in the Modified
   Version, together with at least five of the principal authors of the
   Document (all of its principal authors, if it has fewer than five),
   unless they release you from this requirement.
C. State on the Title page the name of the publisher of the
   Modified Version, as the publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modifications
   adjacent to the other copyright notices.
F. Include, immediately after the copyright notices, a license notice
   giving the public permission to use the Modified Version under the
   terms of this License, in the form shown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections
   and required Cover Texts given in the Document's license notice.
H. Include an unaltered copy of this License.
I. Preserve the section Entitled "History", Preserve its Title, and add
   to it an item stating at least the title, year, new authors, and
   publisher of the Modified Version as given on the Title Page.  If
   there is no section Entitled "History" in the Document, create one
   stating the title, year, authors, and publisher of the Document as
   given on its Title Page, then add an item describing the Modified
   Version as stated in the previous sentence.
J. Preserve the network location, if any, given in the Document for
   public access to a Transparent copy of the Document, and likewise
   the network locations given in the Document for previous versions
   it was based on.  These may be placed in the "History" section.
   You may omit a network location for a work that was published at
   least four years before the Document itself, or if the original
   publisher of the version it refers to gives permission.
K. For any section Entitled "Acknowledgements" or "Dedications",
   Preserve the Title of the section, and preserve in the section all
   the substance and tone of each of the contributor acknowledgements
   and/or dedications given therein.
L. Preserve all the Invariant Sections of the Document,
   unaltered in their text and in their titles.  Section numbers
   or the equivalent are not considered part of the section titles.
M. Delete any section Entitled "Endorsements".  Such a section
   may not be included in the Modified Version.
N. Do not retitle any existing section to be Entitled "Endorsements"
   or to conflict in title with any Invariant Section.
O. Preserve any Warranty Disclaimers.

If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all
of these sections as invariant.  To do this, add their titles to the
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.

You may add a section Entitled "Endorsements", provided it contains
nothing but endorsements of your Modified Version by various
parties--for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a
standard.

You may add a passage of up to five words as a Front-Cover Text, and a
passage of up to 25 words as a Back-Cover Text, to the end of the list
of Cover Texts in the Modified Version.  Only one passage of
Front-Cover Text and one of Back-Cover Text may be added by (or
through arrangements made by) any one entity.  If the Document already
includes a cover text for the same cover, previously added by you or
by arrangement made by the same entity you are acting on behalf of,
you may not add another; but you may replace the old one, on explicit
permission from the previous publisher that added the old one.

The author(s) and publisher(s) of the Document do not by this License
give permission to use their names for publicity for or to assert or
imply endorsement of any Modified Version.


5. COMBINING DOCUMENTS

You may combine the Document with other documents released under this
License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its
license notice, and that you preserve all their Warranty Disclaimers.

The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
copy.  If there are multiple Invariant Sections with the same name but
different contents, make the title of each such section unique by
adding at the end of it, in parentheses, the name of the original
author or publisher of that section if known, or else a unique number.
Make the same adjustment to the section titles in the list of
Invariant Sections in the license notice of the combined work.

In the combination, you must combine any sections Entitled "History"
in the various original documents, forming one section Entitled
"History"; likewise combine any sections Entitled "Acknowledgements",
and any sections Entitled "Dedications".  You must delete all sections
Entitled "Endorsements".


6. COLLECTIONS OF DOCUMENTS

You may make a collection consisting of the Document and other documents
released under this License, and replace the individual copies of this
License in the various documents with a single copy that is included in
the collection, provided that you follow the rules of this License for
verbatim copying of each of the documents in all other respects.

You may extract a single document from such a collection, and distribute
it individually under this License, provided you insert a copy of this
License into the extracted document, and follow this License in all
other respects regarding verbatim copying of that document.


7. AGGREGATION WITH INDEPENDENT WORKS

A compilation of the Document or its derivatives with other separate
and independent documents or works, in or on a volume of a storage or
distribution medium, is called an "aggregate" if the copyright
resulting from the compilation is not used to limit the legal rights
of the compilation's users beyond what the individual works permit.
When the Document is included in an aggregate, this License does not
apply to the other works in the aggregate which are not themselves
derivative works of the Document.

If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one half of
the entire aggregate, the Document's Cover Texts may be placed on
covers that bracket the Document within the aggregate, or the
electronic equivalent of covers if the Document is in electronic form.
Otherwise they must appear on printed covers that bracket the whole
aggregate.


8. TRANSLATION

Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section 4.
Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections.  You may include a
translation of this License, and all the license notices in the
Document, and any Warranty Disclaimers, provided that you also include
the original English version of this License and the original versions
of those notices and disclaimers.  In case of a disagreement between
the translation and the original version of this License or a notice
or disclaimer, the original version will prevail.

If a section in the Document is Entitled "Acknowledgements",
"Dedications", or "History", the requirement (section 4) to Preserve
its Title (section 1) will typically require changing the actual
title.


9. TERMINATION

You may not copy, modify, sublicense, or distribute the Document except
as expressly provided for under this License.  Any other attempt to
copy, modify, sublicense or distribute the Document is void, and will
automatically terminate your rights under this License.  However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.


10. FUTURE REVISIONS OF THIS LICENSE

The Free Software Foundation may publish new, revised versions
of the GNU Free Documentation License from time to time.  Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.  See
http://www.gnu.org/copyleft/.

Each version of the License is given a distinguishing version number.
If the Document specifies that a particular numbered version of this
License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation.  If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation.


ADDENDUM: How to use this License for your documents

To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and
license notices just after the title page:

    Copyright (c)  YEAR  YOUR NAME.
    Permission is granted to copy, distribute and/or modify this document
    under the terms of the GNU Free Documentation License, Version 1.2
    or any later version published by the Free Software Foundation;
    with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
    A copy of the license is included in the section entitled "GNU
    Free Documentation License".

If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
replace the "with...Texts." line with this:

    with the Invariant Sections being LIST THEIR TITLES, with the
    Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.

If you have Invariant Sections without Cover Texts, or some other
combination of the three, merge those two alternatives to suit the
situation.

If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of
free software license, such as the GNU General Public License,
to permit their use in free software.