ARCH チュートリアル (arch Meets hello-world)

Original: http://regexps.srparish.net/tutorial/arch.html
Latest: http://www.gnu.org/software/gnu-arch/tutorial/arch.html
Latest-ja: http://hotcake.halfmoon.jp/doc/tutorial-tla-ja/

分散型SCM

Thomas Lord [FAMILY Given]

[Version: arch-1.0pre17]


目次

1. archの導入
このマニュアルの対象
リビジョン管理とは何か?
どうしてarchを使う必要があるの?
2. 動作に必要なシステム環境
3. arch コマンドの概要
4. 例の要約
5. archに触ってみよう
どのように動作するか — あなたの arch ID
6. 新しいアーカイブの作成
場所の選択
アーカイブ名の決定
アーカイブの作成
これをデフォルトアーカイブとします
どうやって動作するのか — 新しいアーカイブ
7. 新しいプロジェクトの作成
プロジェクトカテゴリの作成
プロジェクトブランチの作成
バージョン番号の選択
なんでこんなことになっているのか
どのように動くか — カテゴリ、ブランチ、バージョンの作成
8. 新しいソースツリーの作成
最初のソース
プロジェクトツリーの初期化
ツリーの初期化は、アーカイブを変更しません
init-tree で失敗したら?
どのように動作するか — 新しいツリーの初期化
9. プロジェクトツリーの目録
名前ベースの目録という概念
inventory コマンド
arch の名前規約
名前規約の様子
名前規約のカスタマイズ
なんでこんなことに — inventory 名前規約について
10. ソースのための目録タグ
全てのファイルについての二つの名前
どうしてそんな仕組みがあるのか — 目録タグの目的
タグに関する選択 — tagging-method の導入
タグづけの方法の設定
名前によるタグづけの利用
明示的なタグづけの方法の利用
暗黙的な目録の利用
物事を単純に保つこと
hello-world プロジェクトのタグづけ
ファイルにタグづけする他の方法
tree-lint を黙らせること
11. 最初のリビジョンのインポート
最初のログファイルの作成
アーカイブ中への最初のリビジョンの保存
インポートからのリビジョン名
どのように働くか — インポートの効果
12. 修正点のチェックイン
warld != world
ログメッセージについてのいくつかのアドバイス
編集/ログ更新のサイクル
ああ、なんてこと — いったい何をしてしまったんだ?
アーカイブへの変更点の保存
どのように動作するか — 新しいリビジョンのコミット
13. 以前のリビジョンの抽出
最後のリビジョンのチェックアウト
もっと以前のリビジョンのチェックアウト
どのように動作するのか — get を使ったリビジョンの抽出
14. 共有アーカイブと、公開アーカイブ
アーカイブのネットワークアクセス登録
一度に複数のアーカイブを使った作業
アーカイブを -A オプションで選択する
完全に修飾されたプロジェクト名
読み込み専用アーカイブ
読み込み専用のアーカイブのミラー
混合アクセスモード
FTP アーカイブの作成
SFTP アーカイブの作成
WebDAV と HTTP アーカイブ
15. update/commit スタイルの共同作業
アリスとボブは main をハックします
ボブが先にコミットします
アリスはまだコミットできません
なぜアリスはコミットすることができないかということについての理解
update コマンド
どのように動作するか — update コマンド
16. チェンジセット入門
mkpatch
dopatch
不完全パッチ処理 — どのようにして衝突が扱われるか
17. チェンジセットの詳細
どのように動くか — commitはアーカイブ中にチェンジセットを保存します
get-patch はアーカイブからチェンジセットを取り出します
チェンジセットを調べるためにはpatch-reportを使います
commit をうまく使うこと — きれいなチェンジセットの概念
18. replay の導入 — update の代わりの方法
update のリフレッシュ機能
リプレイコマンド
どのように動作するか — replay ––in-place
19. 選択したファイルのコミット
すぐに修正することについての問題
ちょっとした問題の修正に対する乱暴な解決方法
commit ––filesを使った、ちょっとした修正問題の解法
20. ブランチの初歩 — プライベートな変更の保守
ブランチのシナリオ — プライベートな変更の必要
ローカルアーカイブにリモートプロジェクトのブランチを作ること
タグの役割
タグリビジョンのキャッシング
新しいブランチの調査
ローカルな変更を加えること
ブランチからのバージョンを更新すること
どのように動作するのか — タグと基本的なブランチについて
21. いくつかの利用に関するアドバイス — プライベートなミラーを作ること
リモートアーカイブのもついくつかの問題
ローカルコピーの保持
22. パッチログとプロジェクトツリー履歴
プロジェクトツリーはパッチログを持っています
どのように動作するか — whats-missing
変更履歴とツリーAncestryの概念
変更履歴
ツリー Ancestry
自動化されたチェンジログ
23. より進んだブランチ — 星型マージスタイルの共同作業
基本的なブランチから、より複雑なブランチへ
簡単な開発ブランチ
開発ブランチのマージ問題
replay は、開発ブランチマージ問題を解決しません
update は開発ブランチマージ問題を解決しません
開発ブランチマージ問題を解くための一つの方法
星型マージ — 一般的な開発ブランチマージ問題の解決
24. シンボリックタグ
25. つまみ食い的修正
26. 複数のツリーのあるプロジェクトと設定管理
27. アーカイブのキャッシュしたリビジョンによる arch の効率化
28. リビジョンツリーライブラリを使った arch の高速化
リビジョンライブラリの場所
リビジョンライブラリの形式
ライブラリへのリビジョンの追加
ライブラリ中のリビジョンの検索
ライブラリからのリビジョンの削除
ライブラリの内容の一覧表示
リビジョンライブラリ中の個々のファイル
あらかじめ必要なパッチセットの決定
29. arch の通知機能を使った処理の自動化
四つの通知設定ファイル
リポジトリ中のすべてに対する通知
通知メール
通知に関する堅牢さの問題
cron によるスケジュール通知
archコマンドからの通知のスケジュール
A. arch のチェンジセット形式
B. 目録の名前規約のカスタマイズ
名前規約をカスタマイズするとき
名前規約のカスタマイズの方法
C. The GNU Free Documentation License
D. The GNU General Public License
E. ここでちょっと・・・助けてもらえないでしょうか?"
30. Indexes :unnumbered :index (general) :index-for "arch"

第1章 archの導入

arch はりビジョン制御、ソースコード管理、そして、 設定管理のためのツールです。

このマニュアルはarchのチュートリアルです。 その目的は、最初にarch使い始める手助けをする ことです。

このマニュアルの対象

このマニュアルを使うためには、基本的な unix コマンドラインツールに精通している べきです。(たとえばls, mv, findのようなコマンドです)。

さらに、diffpatch プログラム、さらに、 patchsetの概念に精通しているべきです。

それはとても役に立ちますが、CVSのような他のバージョン管理 システムを使っているか、少なくとも知っているのであれば、どうしても必要というわけでも ありません。

リビジョン管理とは何か?

リビジョン管理システム」は、複数ファイルからなるツリーや、 それに対する変更のためのライブラリ群と、設定のためのツールを言います。 たとえば、典型的なソフトウェア開発は、時間と共にどのようにプロジェクトの ソースコードが変化していくかを記録し、そのコードに対するそれぞれの変更を 記録し、(バグフィックスや、機能追加など)、そのような変更をプロジェクトに かかわっているすべてのプログラムで共有し、それらが正しく同期するようにし、 一つのソースツリーに対して異なる時間、異なるプログラマがほどこした修正 をまとめるために、リビジョン管理システムを利用します。

ソース管理ツール」は、「手で」現実的に記録すること ができる以上のファイルがある場合でも、そのようなソースツリーを管理するのを 助けるようなソフトウェアのことを言います。たとえば、ソース管理ツールは ツリー中のソースファイルの目録を作成し、ソースファイルを 一時ファイルや、同じ場所に保存されているほかのファイルと区別し、 ソースファイルが追加や削除されたようなときに、そのことを伝えます。

設定管理」は複数の分離して管理されているソースツリーを 一つのツリーにまとめるようなプロジェクトの要求を取り扱います。設定 管理ツールは統合されたプロジェクトを簡単に構築し、それぞれの部分での 開発がどのように同期されるかを記録するのを支援します。

どうしてarchを使う必要があるの?

archは競合するソフトと比較して、いくつもの利点を持って います。その中のいくつかは以下のようなものです:

ツリー全体の上での作業 archはツリー全体を記録します — 単に個別のファイルを管理するだけではありません。たとえば、 もしツリー中のたくさんのファイルを変更した場合、archはファイルごとの 変更ではなく、その変更すべてを一つのグループとして記録することができます。 もしファイル名を変更するか、ツリー中で移動した場合、archは そのようなツリーの形状の変化を、ファイルの内容に関する変更と共に記録することが できます。

チェンジセット指向 archは単にプロジェクトツリーの"スナップショット"をとる だけではありません。そのかわりに、archはそれぞれの リビジョンを特定のチェンジセットと関連づけます。チェンジセットとは、 変更内容にについての完全な記述のことです。archは、 チェンジセットの内容を見たり、チェンジセットを適用してツリーをマージしたり、 どのようなチェンジセットが適用されたかを問うことによってあるツリーの履歴を 調べたり、などなど、といったことを支援するようなチェンジセット指向のコマンドを 用意しています。

完全な分散システムであるということ archは"中心的なリポジトリ"に依存しません。 たとえば、すべての重要な貢献者に、プロジェクトアーカイブに対する 書き込み権限を与える必要がありません。そのかわり、それぞれの貢献者は 自分の作業のために、自分自身のアーカイブを持つことができます。 archはアーカイブ境界をまたいで、シームレスに 操作することができます。

第2章 動作に必要なシステム環境

archを利用するには、すでに利用できるいくつかのソフトウェアツールが 必要になります。そのようなツールはPATHに存在している必要は ありません — arch は必要があれば、独自のPATH を利用することができます。

GNU Make archを構築するには、GNU Make が 必要です。

GNU Tar GNU tarが必要です。 もっと正確には、以下のようなオプションを持つ tar のバージョンが 必要です:

-zcf F

Fという名前の gzipで圧縮されたtarファイルを作ります。ここで F は -でもよく、この場合 tar ファイルは標準出力ストリームに 書き出されます。

-zxf F

F という名前の gzip圧縮されたファイルからファイルを抽出します。ここで F は -でもよく、この場合標準入力ストリームから tar ファイルを 読み出します。

-T -

このオプションは標準入力からファイルの一覧を読み込みます。そのような ファイルだけがアーカイブから読んだり書いたりする対象になります — 他のものは無視されます。

-m

ファイルを抽出するとき、修正時刻を復元しません。

GNU diff と GNU patch かなりの熟考の結果、archGNU のバージョンのdiffpatchに依存させることに決めました。 もっと正確には、「unified 形式」の出力(-uオプション) を生成することができ、その形式を理解でき、–– posixを理解することが できるようなバージョンのpatchが必要です。 (「文脈 diff」を使うことはささいなことで、そのため、標準的な diffpatchを使うことも、たいしたことではない のかも知れませんが、unified diff はもっとずっと読みやすく、このような重要な サブコマンドの特定の実装を選択することが、archの長期的な安定性 に寄与すると信じています)。

標準的なPosixのシェルツール パッケージのフレームワークは、標準的な Posix のシェルツールがシステムで利用可能で あることを仮定しています。現時点では sh/bin/shにインストールされている 必要がありますが、今後のリリースでは修正されるかも知れません:

        awk
        cat
        chmod
        date
        echo
        find
        fold
        grep
        head
        ls
        mkdir
        printf
        pwd
        rm
        sed
        sh
        tee
        test
        touch
        tsort
        wc
        xargs

通常の -exec 拡張を持った find findのバージョンは、長い文字列の文脈でも{} を展開 できるものである必要があります。たとえば:

        find . -exec echo ">>>{}<<<" ";"

は、 '>>>' と '<<<' で囲まれたすべてのファイルとディレクトリの一覧 を出力すべきです。GNU find はこのような性質を持っていますが、 ほとんどの実装でもそうでしょう。(Posix は明示的には{} が単独である 場合にのみ展開されるように要求しているだけで、長い文字列中に{} が 埋め込まれた場合についてはその意味を定義していません。)

null デバイス システムは、/dev/nullを持っていなくてはなりません。 /dev/null に向けた出力は、通常のやり方で、単に消えてしまう べきです。

BSD columnプログラム — おそらく もしプログラムcolumnPATH 上に存在 するなら、(あるいはarchによって利用されるパス上に存在 するなら)、それは入力をコラムに書式するものであり、-xオプション で行の前に列を埋めるものであるべきです。もしこのプログラムが見つからない場合には それは利用されません。

第3章 arch コマンドの概要

archのすべてのコマンドはプログラムlarch経由で アクセス可能です。通常のサブコマンドの構文を使います。

        % larch <sub-command> <options> <parameters>

サブコマンドの一覧は以下のように取得することができます:

        % larch --help-commands

それぞれのコマンドのほとんど完全なドキュメントはそれぞれのヘルプメッセージ から利用可能です。このarchのヘルプメッセージはおおざっはに言って 伝統的な unix のman ページにあたるものです。たとえば、以下のように 実行してみると:

        % larch make-archive --help
        create a new archive directory
        usage: make-archive [options] (-u | name) directory

                -V --version                  print version info
                -h --help                     display help
                -r --readme file              save FILE as the README
                                              for this archive
                -u --update                   update an existing archive

	NAME is the global name for the archive.  It must be an
	email address with a fully qualified domain name, optionally
	followed by "--" and a string of letters, digits, periods
	and dashes.

        [....]

オプション名と引数の構文に関しては、コマンド間で非常に大きな規則性があります。 さまざまなコマンドを学ぶ中で、これを理解してもらえればと思います。

第4章 例の要約

後の章でlarchのサブコマンドが具体的な例を通じて 徐々に導入されます。この章では単にあなたが学ぶであろうコマンドの大部分を 単に要約した形で示します:

自分のarch ユーザIDの設定 第5章


        % larch my-id "Tom Lord <lord@emf.net>"

        % larch my-id
        Tom Lord <lord@emf.net>

新しいアーカイブの作成 第6章

        % larch make-archive lord@emf.net--2003-example \
                             ~/{archives}/2003-example

        % larch my-default-archive lord@emf.net--2003-example
        default archive set (lord@emf.net--2003-example)

        % larch my-default-archive
        lord@emf.net--2003-example

        % larch archives
        lord@emf.net--2003-example
                /home/lord/{archives}/2003-example

        % larch whereis-archive lord@emf.net--2003-example
        /home/lord/{archives}/2003-example

新しいプロジェクトの開始 第7章

        % larch make-category hello-world
        % larch make-branch hello-world--mainline
        % larch make-version hello-world--mainline--0.1

        % larch categories
        hello-world

        % larch branches hello-world
        hello-world--mainline

        % larch versions hello-world--mainline
        hello-world--mainline--0.1

新しいソースツリーの開始 第8章

        % cd ~/wd/hello-world

        % larch init-tree hello-world--mainline--0.1

        % larch tree-root
        /usr/lord/wd/hello-world

        % larch tree-version
        lord@emf.net--2003-example/hello-world--mainline--0.1

プロジェクトツリーの目録(Inventories) 第9章 参照。

        % larch inventory --source
        [....]

ソースのための目録タグ(Inventory Tags) 第10章 参照。

        % larch tagging-method implicit

        % larch tagging-method
        implicit

最初のリビジョンのインポート 第11章

        % cd ~/wd/hello-world

        % larch make-log
        ++log.hello-world--mainline--0.1--lord@emf.net--2003-example

        [edit the log message adding a summary and message body]

        % larch import
        [....]

        % larch revisions hello-world--mainline--0.1
        base-0

チェックインによる変更 第12章

        % cd ~/wd/hello-world

        % larch make-log
        ++log.hello-world--mainline--0.1--lord@emf.net--2003-example

        [edit the log message adding a summary and message body]

        % larch commit
        [....]

        % larch revisions hello-world--mainline--0.1
        base-0
        patch-1

        % larch revisions --summary hello-world--mainline--0.1
        base-0
            initial import
        patch-1
            Fix bugs in the "hello world" string

以前のリビジョンの抽出 第13章

        % larch get hello-world--mainline--0.1 hello-world
        [...]

        % larch get hello-world--mainline--0.1--base-0 hello-world-0

共有と公開アーカイブ 第14章

HTTP と WebDAV のアーカイブ:

    % larch register-archive lord@emf.net--2003 \
            http://regexps.srparish.net/{archives}/lord@emf.net--2003

FTP アーカイブ:

    % larch register-archive lord@regexps.com--2002 \
            ftp://ftp.regexps.com/{archives}/lord@regexps.com--2002

アップデートとコミットのスタイル: 第15章

        % larch whats-missing
        patch-2

        % larch whats-missing --summary
        patch-2
            commented return from main

        % larch cat-archive-log hello-world--mainline--0.1--patch-2

チェンジセット 第16章第17章

        % larch mkpatch ORIGINAL MODIFIED DESTINATION

        % larch dopatch PATCH-SET TREE

        % larch get-patch hello-world--mainline--0.1--patch-1 patch-1

        % larch patch-report --diffs patch-1

replay コマンド 第18章

        % larch replay --in-place .

選択されたファイルのコミット ???

        % larch commit --files -- file-a.c file-b.c

ブランチの初歩 第20章

    % larch tag \
        lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1 \
        hello-world--candice--0.1

   % larch archive-cache-revision hello-world--candice--0.1--base-0

   % larch archive-cached-revisions hello-world--candice--0.1

   % larch log-for-merge

第5章 archに触ってみよう

archを使う最初のステップは、以下のようなコマンドで自分のIDを設定することです:

	% larch my-id "Tom Lord <lord@emf.net>"

IDは自分の名前の後にemailアドレスを角カッコでくくって続けたものです。

arch は作成するさまざまなログメッセージに あなたのIDを記録します。

自分のIDは以下のようにして知ることができます:

        % larch my-id
        Tom Lord <lord@emf.net>

どのように動作するか — あなたの arch ID

上のコマンドの後では、自分のホームディレクトリに以下のような新しい ファイルができます:

        % ls ~/.arch-params
        =id

        % cat ~/.arch-params/=id
        Tom Lord <lord@emf.net>

注意: ~/.arch-params/の中のファイルを「手で」 編集しないでください。

第6章 新しいアーカイブの作成

アーカイブは、arch がプロジェクトツリーとチェンジセットの ライブラリを保持するために用意されたディレクトリです。この章では、どのようにして 新しいアーカイブを作るかを説明します。

場所の選択

アーカイブを保存する場所を決めなくてはなりません: アーカイブを 含むディレクトリをどこに作るか、ということです。

アーカイブの利用方法: 結局は一個以上の アーカイブが欲しいくなることが多いので、 複数のアーカイブを置くための専用のディレクトリを作るのは良い考えです。

以下の例では~/{archives}のサブディレクトリとしてアーカイブ を作ることにします。~/{archives}は、アーカイブ用の専用 ディレクトリです。

	# Create a directory in which to store archives:
	#
	% mkdir ~/{archives}

アーカイブ名の決定

次に、アーカイブの名前を決める必要があります。アーカイブの名前はemailアドレスのあとに ダッシュを二つ続け(––)さらにその後に接頭辞をつけます。 便宜性を考えて、emailアドレスはアーカイブ所有者のものとすべきです。

例として、以下のような名前を使います:

	lord@emf.net--2003-example

アーカイブの利用方法: もし一つのアーカイブを非常に長い期間にわたって利用する場合、最終的には非常に大きな データが蓄積され、作業を続けるのに不便になることがあります。 arch は、アーカイブの境界をまたいで透過的な操作ができるので、 ただ一つのアーカイブにすべてを保存する必要はありません。時間 の経過とともに、アーカイブを分割する計画を立てるのは良い考えで、そのためアーカイブ名 には日付を含めることをお勧めします。今回の例では、アーカイブは2003と ラベルづけされています: 一年後、lord@emf.net––2004-example という名前の アーカイブを作り、その新しいアーカイブでプロジェクトを続けることができます。 2003 アーカイブも、そのまま存在します — 単に、もうそこには 新しいデータを追加しないというだけのことです。

アーカイブの利用方法: 複数のアーカイブを保管することを考えて、アーカイブの名前はそれぞれを区別するような ものにすべきです。上の例で-example の接頭辞はこのアーカイブが 単にチュートリアルの例として利用されるために作られたということを示しています。

アーカイブの作成

新しいアーカイブを作るにはmake-archiveコマンドを使います。 アーカイブの名前と、場所を指定します:

        # Create the new archive
        #
        % larch make-archive lord@emf.net--2003-example \
                             ~/{archives}/2003-example

これをデフォルトアーカイブとします

今後の操作で必要なコマンドのすべてにアーカイブ名を指定する手間を省くため、 新しいアーカイブをデフォルトであると宣言します:

        # Choose a default archive
        #
        % larch my-default-archive lord@emf.net--2003-example
        default archive set (lord@emf.net--2003-example)

現在のデフォルトアーカイブは以下のようにして表示できます:

        % larch my-default-archive
        lord@emf.net--2003-example

そして、デフォルト設定は以下のようにして取り消すことができます:

        % larch my-default-archive -d
        user default archive removed

(もしこの-dオプションを実際に試してみた場合は デフォルトアーカイブをもう一度設定し、以下の例を続けていけるようにして おいてください)

どうやって動作するのか — 新しいアーカイブ

そのコマンドが何をするのか見てみましょう。

まず、larch は、新しいアーカイブについて知っています:

        # What archives does larch know about?
        #
        % larch archives
        lord@emf.net--2003-example
                /home/lord/{archives}/2003-example
        % larch whereis-archive lord@emf.net--2003-example
        /home/lord/{archives}/2003-example
        # Where is that data stored?
        # 
        % ls ~/.arch-params
        =default-archive   =id             =locations
        % cat ~/.arch-params/=default-archive
        lord@emf.net--2003-example
        % ls ~/.arch-params/=locations
        lord@emf.net--2003-example
        % cat ~/.arch-params/=locations/lord@emf.net--2003-example
        /home/lord/{archives}/2003-example

次に、アーカイブディレクトリは作成され、何行かが含まれています:

        % ls ~/{archives}
        2003-example
        % ls -a ~/{archives}/2003-example
        .                .archive-version
        ..               =meta-info
        % cat ~/{archives}/2003-example/.archive-version
        Hackerlab arch archive directory, format version 1.
        % ls -a ~/{archives}/2003-example/=meta-info/
        .       ..      name
        % cat ~/{archives}/2003-example/=meta-info/name
        lord@emf.net--2003-example

注意: ~/.arch-params/ の中のファイルや、アーカイブ中のファイルを 「手で」編集しないでください。

第7章 新しいプロジェクトの作成

こことあとの章では、"hello world"プログラムの例を通じて、archを 使った簡単なプロジェクトをどうやって設定したり管理したりするかを見ていきます。

プロジェクトカテゴリの作成

hello-world プロジェクトの最初のステップとして、アーカイブに 新しい"プロジェクトカテゴリ"を作ってみます。

        % larch make-category hello-world

アーカイブ中の全てのカテゴリの一覧を表示させることで、新しい カテゴリがうまく作成できたかどうか確認することができます:

        % larch categories
        hello-world

プロジェクトブランチの作成

arch ではプロジェクトにブランチを作ることで、作業を分割する ことができます。

おおざっぱに言って、ブランチとはプロジェクトを二つ以上の部分に分けて、 お互いがほぼ独立しているような形にするしくみです。 例えば、hello-worldプロジェクトに二つのことをさせたいと します:

1) 伝統的なhello-worldの通常のリリースを作成し、単純なバグを修正し、 プログラムを移植し、重要ではない機能追加をすること

2) hello-worldにGUIインターフェースを追加する必要があり、 それには、だいたい一年くらいの開発期間がかると見込まれる

この二つの作業を並行してやりたいが、お互いに干渉させたくないとします。 例えば、うまく動作することが確認できるまでは、通常のリリースコード中に GUIのコードを混在させたくありません。

そのような場合、ブランチを使うことができます: 一つは通常のリリース用として(主系ブランチと言います)そして もう一つはGUI機能つきのものです(guiブランチと言います)。

ブランチには他にもいろいろな使い方があり、いくつかはこのマニュアルの後の ほうで説明します。いまの場合は、ひとつのブランチが必要になるだけです: hello-worldの公式な最新ソースのためのブランチです:

        % larch make-branch hello-world--mainline
                            ^^^^^^^^^^^  ^^^^^^^^
                                |            |
                                |       branch name
                          category name

カテゴリ名とブランチ名は二つのダッシュで区切られていることに注意して ください。一般的に言って、カテゴリ名とブランチ名は英文字とダッシュのみ を含み、英文字で始め、二つのダッシュを含んではならず、最後がダッシュ で終ってはなりません。

hello-worldカテゴリ中のブランチの一覧を取得するコマンド を確認することは簡単です。

        % larch branches hello-world
        hello-world--mainline

バージョン番号の選択

最後に、作業しようとしているhello-worldのバージョン番号を選択し、 そのバージョンをアーカイブに作る必要があります。

archのバージョン番号は、特定の「スナップショット」やプロジェクト のリリースの名前ではありません — そのような概念と関係しては いますが。正確には、バージョン番号は"開発ライン"の名前です: 開発ラインとは、特定のリリースを 作るときに加えた修正の並びです。

今回の例で、ブランチ中で新しい開発ラインを始めることができます:

        % larch make-version hello-world--mainline--0.1
                                                    ^^^
                                                     |
                                          version number

バージョン番号は常に二つの正の整数をピリオドで繋げたものです。 この二つの番号はよくメジャー番号マイナー番号 と呼ばれます。

ブランチ中にどのようなバージョンがあるかを表示させて、新しいバージョンを確認することが できます:

        % larch versions hello-world--mainline
        hello-world--mainline--0.1

なんでこんなことになっているのか

arch を使うのが初めての人はよく、アーカイブ構造の厳格な構成に 驚くようです。よくある二つの質問(と答え)は:

どうしてカテゴリ、ブランチ、バージョンなどという概念が あるのか? どうして好きな文字列でプロジェクトの名前をつけることができない のか? この質問は、リビジョン管理システムがライブラリ管理システム である、ということを思い出せば理解できると思います。 その仕事のひとつは、非常に大きなプロジェクトやソースコードの集まりを 閲覧したり検索したりするのを支援することです。そのような検索を現実的なものにするため、 archカテゴリシステムを定義しています: つまり、カテゴリ、ブランチ、バージョンがそれです。 (リビジョン管理とは何か?項参照)

これは、デューイの分類表のような、本のライブラリで使われるカテゴリシステム に何か似ているところもあります: ライブラリにあるすべては階層的に カテゴリ化されています。それは、あるアイテムがどこに保管されているかを 示すための統一的な方法で、さまざまなアイテム間の関係を示唆することによって 検索を支援します。たとえば、ブランチは同じカテゴリ中のほかのブランチとよく 似ているはずです。大きなメジャーバージョン番号を持ったディレクトリは、 同じブランチにある、より小さなメジャーバージョン番号を持ったものよりも あとで作られた作業を含んでいるはずです。

この類推は完全ではありません: デューイのような本のカタログシステムは、公式な カテゴリとサブカテゴリのリストに基づいていますが、archでは 自分でカテゴリ名を選ぶことができます。しかし、それでもなおarch は検索や閲覧を簡単にするために、関連するアイテムのグループ化のアイディアに 基づいています。そして、デューイが人々がどのようにして本を検索するかという 共通のパターンを把握することを意図していたのと同様、arch もソースアーカイブ中を人々がどのように検索するかという共通のパターンを捉える ことを意図しています。

なぜ、バージョン番号は二つの部分を持っているのか? 人によっては<major>.<minor> バージョン番号の 制約を好きになれないようです:0.1のかわりに、0.1.1 のような番号体系を好む、などです。

実際、この制約は、最終的にはarchから取り除かれることになるでしょう。 しかし現時点では、二つのバージョン番号体系の統一性は、unix の標準的なsort プログラムを使って、arch のバージョン番号の任意のリストをソートする ことをより簡単なものとしています。archは、sort のような標準的なツールと簡単に連携できることに非常に大きなプライオリティをおいています。

どのように動くか — カテゴリ、ブランチ、バージョンの作成

make-category, make-branch, そして make-version のようなコマンドは実際には何をするのでしょうか? それは概念的には非常に簡単なことです: アーカイブ中に新しいディレクトリを作ります。

        % larch whereis-archive lord@emf.net--2003-example
        /home/lord/{archives}/2003-example

        % cd `larch whereis-archive lord@emf.net--2003-example`

カテゴリは最上位のディレクトリです:

        % ls
        =meta-info      hello-world

ブランチは次の階層です:

        % ls hello-world
        =README         hello-world--mainline

Versions the third:

        % ls hello-world/hello-world--mainline
        =README         hello-world--mainline--0.1

バージョンもそれ自身、ディレクトリです:

        % ls hello-world/hello-world--mainline/hello-world--mainline--0.1/
        +revision-lock  +version-lock   =README

注意: =README ファイルには 誰がカテゴリ、ブランチ、リビジョンを作り、またそれがいつかという情報が含まれて います。これらのファイルはアーカイブ中のファイルを手で編集してはいけない、 という通常の規則の 唯一の例外になっています。 これらのファイルに含まれているヘッダーフィールド部分から空行で区切られた後 の部分に、新しい任意のテキストを追加することができます。

注意: ロックファイル(たとえば+revision-lock) は arch によって内部的に利用されます。新しいデータをアーカイブに追加するとき、arch は単にmkdirを呼び出すわけではありません。そのかわり、同時に実行されている ほかのコマンドや、あるコマンドが実行途中でkillされたかどうか、などにかかわらず常に一貫した状態 を保つために、アーカイブを注意深く変更します。

第8章 新しいソースツリーの作成

前章までの例をたどってきたのなら、新しいアーカイブと その中に新しいhello-worldプロジェクトができているはず です。

この章では、そのプロジェクトの一部となるソースツリーを用意する ステップをたどってみたいと思います。

最初のソース

説明のため、初期状態としてすこしバグのあるhello-world の実装があるものとします:

        % cd ~/wd

        % ls
        hello-world

        % cd hello-world

        % ls
        hw.c    main.c

        % cat hw.c

        #include <stdio.h>

        void
        hello_world (void)
        {
          (void)printf ("hello warld");
        }
        
        
        % cat main.c
        
        extern void hello_world (void);
        
        int
        main (int argc, char * argv[])
        {
          hello_world ();
          return 0;
        }

プロジェクトツリーの初期化

ソースコードを用意する最初のステップは、普通のソースツリーを、"プロジェクトツリー" の形に変えることです:

        % cd ~/wd/hello-world

        % larch init-tree hello-world--mainline--0.1

        % ls
        hw.c    main.c  {arch}

これから作業するアーカイブ中のバージョン名を、init-treeコマンドに 渡していることに注意してください。init-treeは、新しいサブディレクトリ をツリーのルート({arch})に作ります。

{arch} サブディレクトリは、プロジェクトツリーのルートであることを 示しています:

        % larch tree-root
        /usr/lord/wd/hello-world

larch は、このツリーがどのアーカイブバージョンのためのもので あるかを知っています:

        % larch tree-version
        lord@emf.net--2003-example/hello-world--mainline--0.1

最後に、archinit-treeに渡す バージョンのために、patch logと呼ばれるものを 作ります:

        % larch logs
        lord@emf.net--2003-example/hello-world--mainline--0.1

あとの章で、patch log がなんのためにあるのかを説明します。

ツリーの初期化は、アーカイブを変更しません

いままで、プロジェクトツリーを単にソースとしてだけ見てきました: アーカイブ中にまだ何も新しいものは保存していません。これからそうしようと 思いますが、その前に、最初に触れておかなくてはならな重要なトピックが あります: ソースの目録です。次の章でこれについて 触れます。

init-tree で失敗したら?

上の例で間違ってタイプしたとしましょう:

        % larch init-tree hello-world--mainlin--0.1

ひとつの「乱暴な」解決法は、単に{arch}サブディレクトリ を削除して、もう一度やり直すことです。しかし、後のことを考えると、この方法は望ましく ありません:{arch}サブディレクトリは削除したくないようなデータも 含んでいるからです。それで、あとでもっと高度なコマンドを導入します。

init-treeのあやふやな呼び出しの後で、ふたつの問題がおこります。 以下のコマンドの両方の出力は、望んでいるものではありません:

        % larch tree-version
        lord@emf.net--2003-example/hello-world--mainlin--0.1

        % larch logs
        lord@emf.net--2003-example/hello-world--mainlin--0.1

ツリーのtree-versionはいつでも変えることができます:

        % larch set-tree-version hello-world--mainline--0.1
        
        % larch tree-version
        lord@emf.net--2003-example/hello-world--mainline--0.1

パッチログは、少し技巧的です。不要なログを消さなくてはなりません。 そしてその後で、望んでいる内容のログを追加します。

        % larch add-log hello-world--mainline--0.1

        % larch logs
        lord@emf.net--2003-example/hello-world--mainlin--0.1
        lord@emf.net--2003-example/hello-world--mainline--0.1

        % larch remove-log hello-world--mainlin--0.1

        % larch logs
        lord@emf.net--2003-example/hello-world--mainline--0.1

警告: remove-log は危険なコマンドです: それは、指定したときには必要になるパッチログを削除してしまいます。remove-logは 上でやったように、削除されるログが本当に自分の望んだものではない時に限って利用すべきです。

どのように動作するか — 新しいツリーの初期化

init-tree{arch} サブディレクトリを、ソースツリーの 最上位につくります。その中には何があるのでしょうか?

        % ls {arch}
        ++default-version       hello-world

        % cat {arch}/++default-version
        lord@emf.net--2003-example/hello-world--mainline--0.1

{arch}/hello-world は、かなり深いツリーのルートになっています。 パッチログは、そのツリー中に保存されます。

注意: 当り前ですが、 {arch}ディレクトリの中を手で 編集しないでください。

第9章 プロジェクトツリーの目録

注意: 学習曲線について: この章で導入される概念とコマンドは、他のバージョン管理システムを使ったことが あるとしても、たぶんあなたにとってなじみのないものでしょう。 最初のハードルを越えてしまえば、それは本当にとても単純なものです。— そして、その後ではとても便利なものだとわかるでしょう。

名前ベースの目録という概念

プロジェクトツリー中で、いくつかのファイルとディレクトリは「プロジェクト の一部」です — そのようなファイルはarchの興味 をひきます。他のファイルやディレクトリはゴミファイルであったり、編集時のバック アップファイルであったり、プログラムで生成された一時ファイルや中間ファイルで あったりします。そのようなファイルは、ほとんどのarch コマンドでは無視されるか特別の扱いを受けます。

この章ではarchがどのようにしてあるファイルに注目し、他のファイル を無視するかについて議論します。

inventory コマンド

コマンド larch inventory は、ソースファイルの一覧を表示する のに利用されます。それはたくさんのオプションをとりますが、その中には、他の種類 のファイルの一覧を表示するものもあります(たとえば、編集時バックアップファイルや ソースコード以外のファイルのすべての一覧をとるようなものです)。

何かの編集後、ソースツリーが以下のようになったとしましょう:

        % ls
        hw.c            hw.c.~1~        main.c          {arch}

ファイル hw.c.~1~ はエディタのバックアップファイルです。 larch はそれを理解し、ソース目録からそのファイルを除外します。

        % larch inventory --source
        ./hw.c
        ./main.c

larch はソースの一覧以外の一覧も表示することができます:

        % larch inventory --backups
        ./hw.c.~1~

arch の名前規約

この章は他の種類のファイルからソースファイルを選択するために archによって利用される名前規約について説明します。

名前規約はファイルのいくつかの分類に基づいています:

        . and ..                この二つは単に arch によって無視されます

        excluded                Excluded ファイルは普通ファイル一覧からは
                                省略されますが、––all
                                フラグがinventoryに渡される
                                と、以下のカテゴリのどれかの中に置かれ
                                一覧に含まれるようになります。

        source                  これはもちろんソースファイルのことです

        precious                自動的に削除されるべきではないような
                                ソース以外のファイルです

        junk                    自動的に削除されるかも知れないソース以外
                                のファイルです

        backups                 自動的に削除されるかも知れないソース以外
                                のファイルですが、削除しようとするプログラム
                                はそれをエディタのバックアップファイルと
                                して扱うべきです(たとえば、その中の一番古い
                                ものと最新のものを保存しておく、など)

        unrecognized            arch が分類の仕方を知らないようなファイルです
                                — そのような名前規約にも当てはまらないか
                                "疑わしい" 名前を持ったファイルです。

名前によってファイルを分類するアルゴリズムにはいくつかの規則があります。 ファイル名それぞれに、そのような規則が、上のリストの順番でひとつひとつ チェックされ、そのファイルに当てはまる最初の規則にたどり着くまで続け られます。

ドットファイルの除外 特別なファイル... は常に目録一覧から 除外されます。

可搬ではない名前は認識されません 空白を含んだり、印字できない文字を含んでいたり、「グラブ文字」 を含んでいるファイルは常に認識不能として分類されます。 グラブ文字とは:

        ? [ ] * \

除外ファイルのテスト inventoryに、––all フラグが 与えられない場合、除外ファイルのパターンにマッチしたファイル名は 一覧から削除されます。もしディレクトリの名前が除外されると、そのディレクトリ の内容全体がスキップされます。デフォルトでは除外ファイルのパターンは、 arch自身が作った制御ファイルにマッチします:

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

ゴミファイルのテスト このステップまで到達したすべてのファイルのうち、二つのコンマ (,,) で始まるものは、ゴミファイルとして 分類されます。arch 自身によって作られる一時ファイルは二つの コンマで始まります。さらにゴミのパターンと一致するようなファイルはすべて ゴミファイルとして分類されます。デフォルトでは、 そのパターンは(少なくとも)ひとつのコンマで始まるようなすべての名前にマッチ します。

        ^,.*$

このデフォルトパターンを使って、小技をきかせることができます。 もしソースツリー中にゴミのファイルを作りたい場合、その名前の先頭をコンマ から始まるものにしてください。

バックアップファイルのテスト デフォルトでは、バックアップファイルはこのテストまで到達したファイルのうち、 以下のどれかのパターンにマッチするもののことです:

        ^.*(~|\.~[0-9]+~)$
        ^.*\.bak|\.orig|\.rej|\.original|\.modified|\.reject)$

特殊ファイルのテスト デフォルトでは、特殊ファイルはこのテストまで到達したファイルのうち、 以下のどれかのパターンにマッチするもののことです:

     ^\+.*$
     ^(\.gdbinit|\.#ckpts-lock)$
     ^(=build\.*|=install\.*)$
     ^(CVS|CVS\.adm|RCS|RCSLOG|SCCS|TAGS)$

疑わしいファイルのテスト(認識しない) このテストまで到達したファイルのいくつかは、ソースツリー中におそらく 存在すべきではないだろうという推定のもとで、認識しない ものと して明示的に扱われます。デフォルトでは、以下の拡張子のどれかで終わるような名前は 認識しないものとして扱います:

        .o
        .a
        .so
        .core

さらに、ファイル名core は、(デフォルトでは) 認識しないものとされます。

ソースファイルテスト このテストまで到達したファイルはソースファイルとパターン比較されます。 デフォルトのパー単は以下のようなものです。このパターンは既に出てきた 除外 パターンと重なるかも知れないことに注意してください。 もし––all フラグが inventory に与えられた場合、 除外パターンは利用されず、マッチしたファイルは、 かわりにこのアルゴリズムの後のステップに「素通り」します。

        ^([_=a-zA-Z0-9].*|\.arch-ids|\{arch\}|\.arch-project-tree)$

言い換えると、デフォルトではarchの制御ファイル、制御 ディレクトリは、ソースである(もし除外しなければ)ということになります。 文字、数字、アンダースコア、あるいは等号記号で始まるファイルはソースです。

認識しないファイル このテストまで到達した残りのファイルはすべて、 認識しないものとされます。

名前規約の様子

例として、名前規約のいくつかの様子を見てみましょう。

私達のプロジェクトツリーが以下のような形であったことを思い出してください:

        % ls
        hw.c            hw.c.~1~        main.c          {arch}

それで、普通のソース一覧は:

        % larch inventory --source
        ./hw.c
        ./main.c

すべてのソースファイル(リストから何も除外しない形の場合)は:

        % larch inventory --source --all
        ./hw.c
        ./main.c
        ./{arch}/.arch-project-tree
        ./{arch}/=tagging-method

このリストのディレクトリを含めることもできます:

        % larch inventory --source --all --both
        ./hw.c
        ./main.c
        ./{arch}
        ./{arch}/.arch-project-tree
        ./{arch}/=tagging-method
        ./{arch}/hello-world
        ./{arch}/hello-world/hello-world--mainline
        [... output trimmed ...]

ソースコード以外の一覧を見ることもできます:

        % larch inventory --backups
        ./hw.c.~1~

inventoryコマンドは見たい内容に応じてたくさんのオプションをとります。

名前規約のカスタマイズ

inventory によって利用される、ファイルを分類するための パターンを変更することができます。これについては後の章で説明します (付録B 参照)。

なんでこんなことに — inventory 名前規約について

多くのシステムはソースファイルを認識するための名前規約はありますが、 arch を初めて利用する人はよく、なぜarch がこれほど たくさんのファイルの分類を持っているかを不思議に思うようです。arch が以下のような分類を持っていることを思い出してください:

        excluded
        source
        precious
        junk
        backups
        unrecognized

それぞれのグループの必要性は、以下のように説明できます:

excludedarch の制御ファイルが特に興味を もたないような必要に一般的な場合に目録リストを簡潔な形に保つために用意されただけのものです。 これはlsコマンドの「ドットファイル」を扱う場合とよく似ていて、 inventory に対する––all フラグは、ls に対する-a フラグによく似ています。

sourcearch がソースファイルを他のものと 確実に区別することができるように用意されたものです。たとえば、二つのソースツリーを比較するさい、 archsourceの分類中のファイルのみを比較します。

precious ファイルはarch が、そのままの形 でできる限り保持しようとするファイルです。たとえば、もし arch が あなたのためにプロジェクトツリーのコピーを必要としている場合、source ファイルと一緒にprecious ファイルもコピーします。たとえば、 ソースファイルで作業すると同時に、何かのメモをとっているとします。あなたはそのノート ファイルをソースコードの一部だとして間違って欲しくはありませんが、しかし、そのファイル を失いたくもありません。このような場合、ファイルにprecious に マッチする名前を選びます。(たとえば、+notesのような)

junk プロジェクトツリー上で作業しているときに 「使い捨て」ファイルを作りたいことがよくあります。ちょっとした テストプログラムをコンパイルしたい場合や、あるコマンドの出力結果を保存したい ような場合です。そのようなファイルがある程度たまってきたときに、どのファイルが 大事なもので、どれが消したいものかを注意深く区別せずに、後のほうのファイルだけ を一度に消してしまうことができると便利です。 junk 名はこのような目的にぴったりです。そのような使い捨てファイル を作る場合は、名前を,fooのようなものにしてください。後で 安全確実に以下のようなコマンドを実行することができます:

        % rm ,*

        % find . -name ',*' | xargs rm

        % larch inventory --junk | xargs rm

backups エディタが作るバックアップファイルや、 patch のようなプログラムによって作られるバックアップファイルは よく特殊な扱いが必要になります。たとえばエディタが「番号づけされたバックアップ 」を作る場合、それらはほとんど ゴミファイルに近いもの ですが、すべて消してしまって良いものでもく、その中のどれかだけを削除したいことが あります。

unrecognized ソースツリー中のファイルで、どのような知られたパターンにも (あるいは疑わしい名前にも)当てはまらないようなものは、 たいていの場合、何かがうまくいっていないことを示しています。 そのようなファイルを黙って無視したり preciousjunkであるとして扱ったりする かわりに、arch はこのような例外に明示的なフラグを付けて、 ユーザに警告できるようにします。

全体的に、ファイル名前規約の採用は多くのプログラマにとってなじみのない規則かも 知れませんが、私が強く推奨するもののひとつです。このような規約に従うことは 簡単なことで、それによってinventory や後述の tree-lint のようなツールは、ソースコードを制御できない状態から正常に保つための助けになります。

第10章 ソースのための目録タグ

注意: 学習曲線について: 前の章のように、この章で導入される概念とコマンドは他のリビジョン管理システムを使った ことがあるとしても、あまりなじみのないものだと思います。しかし、ひとたび 「分かってしまえば」非常に自然なものであることがわかるでしょう。 なによりもまず、この章はアーカイブにプロジェクトツリーを保存し始める前にやって おかなくてはならない、最後の重要なステップです。

全てのファイルについての二つの名前

arch の世界では、プロジェクトツリー中の全てのソースファイル(とディレクトリ)は、 ふたつの名前を持ちます: "ファイルパス"と、"目録タグ" です。

ファイルのファイルパスは、常に文字列 ./ で始まり、相対パス名称が続きます。それは、ソースツリー中でそのファイルがどこに あるかを記述するものです。

ファイルの目録タグは、ツリー中のファイルに対して一意になるように つけられた、(ほとんど)任意の文字列です。

普通、ファイルが移動すると、ファイルパスは変わりますが、 その目録タグは保存されます。

たとえば、以下のようなツリーとファイルがあるとします:

        file path               inventory tag
        ---------               -------------

        ./hw.c                  i_tag_hw
        ./main.c                i_tag_main

しかし、その後 hw.chello.cに名称変更しました。 その後では、以下のようになります:

        file path               inventory tag
        ---------               -------------

        ./hello.c               i_tag_hw
        ./main.c                i_tag_main

この章はどのようにしてタグがファイルに割り当てられるか、どのようにして タグが管理されるか、そしてどのようにしてそれらがarch で利用されるか、について説明します。

どうしてそんな仕組みがあるのか — 目録タグの目的

後の章で見るように、arch は、ソースツリーとその中にあるファイルの 変更を管理するのが得意で、そのようなツリーとファイルの 履歴に関する情報を伝えるのも得意です。

例として、アリスとボブがhello_worldプロジェクト上で一緒に作業していると しましょう。アリスは自分のツリーでhw.cに何か変更を加えます。 ボブは自分のツリーで、hw.chello.cに名称変更 します。

どこかの時点で、アリスとボブは、「同期をとる」必要があります。 ボブはアリスのやった変更を取り込まなくてはなりません。アリスはボブがやった 同じファイルの名称変更を取り込まなくてはなりません。

arch は同期をとるためのたくさんの仕組みを用意しています — それはarchがやることのできる最も重要なことの一つです — しかし、そのようなことのほとんどすべては、結局、changesets を計算することに帰着します。

アリスは arch に対して、彼女がやった変更を記述するチェンジセットを 作ることができ、そのチェンジセットは、彼女がhw.cにやった変更を 記述するものになるでしょう。ボブもチェンジセットを作ることができ、それは自分のした ファイル名称の変更を記述するようなものになるでしょう。

もしアリスが、ボブのチェンジセットを自分のツリーに適用すると、彼女のhw.c のコピーは、hello.cに名称変更されます。しかし、もう少し面倒なケースは 次のようなものです: もしボブが、アリスのチェンジセットを自分のツリーに適用すると、 何がおこるか? です。

アリスは ./hw.c という名前のファイルを変更しましたが、ボブのツリーの 中では、同じ変更は、./hello.cという名前のファイルに対して行われる べきです。幸運にも両方のファイルは同じ目録タグを持ちます:

        file path               inventory tag
        ---------               -------------

                 Alice's tree:
        ./hw.c                  i_tag_hw

                 Bob's tree:
        ./hello.c               i_tag_hw

アリスのチェンジセット中では、アリスのした変更は、タグがi_tag_hw であるようなファイルに対してなされた、という記述になります。

そのため、ボブのツリーに対してチェンジセットが適用されるとき、archは 同じタグを持つようなファイルにたいしてチェンジセットを適用することを知っています: それは、変更をボブの./hello.cに対して適用することを知っているわけです。

この例で、目録タグがなんのためにあるかが分かります: 目録タグは、arch が、ファイルの物理的な場所ではなく、論理的な同一性によってツリーに対してなされる変更を 記述することができるようにします。どのようにして目録タグが利用されるかについては もっと複雑なたくさんの例がありますが、ここでは少なくともこの基本的な点を見て来ました。

タグに関する選択 — tagging-method の導入

では、ファイルにたいしてどのような目録タグが与えられるのでしょうか? 一般的に、ファイルシステムは組み込みで、目録タグのような概念をサポート してはいません。オペレーティングシステムは組み込みの目録タグを持って いません。そのため、ユーザは、ファイルにタグを割り当て、その割り当て を管理するために、明示的な操作をする必要があります。

arch はその方法について選択させます。ファイルにタグを 割り当てるための三つの方法があります。最初にプロジェクトを作る時に、 この三つの方法のどれかを選びます。

それらの方法については簡単にここで導入し、詳細はその後に説明することに します。

タグづけの名前による方法 単にタグに関して無視することもできます — まったく利用 しないというものです。これは、タグづけの名前による方法、と呼ばれて います。この方法ではそれぞれのファイルの目録タグは、本質的にはそのファイルのパス名 と同じになります。結果として、ファイルを名称変更した場合、そのタグも変わります。

           The names Method of Tagging


        file path               inventory tag
        ---------               -------------

                Before a rename
        ./hw.c                  ?./hw.c

                 After a rename

        ./hello.c               ?./hello.c

ファイルが名称変更された場合に、ツリー間でその変更を同期させる必要がなければ、 名前によるタグづけは一番簡単な方法です。

タグづけの明示的な方法 明示的な 方法では、目録タグはファイルとは独立に .arch-idsという名前のサブディレクトリに保存されます。 この方法を使うのは、CVSのような古いリビジョン管理システムを使うのと よく似た方法です: もし新しいソースファイルを追加するなら、それにタグをつけるために、 larch addコマンドを使わなくてはなりません。 もしファイルを削除する なら、タグを削除するためにlarch deleteコマンドを使わなくてはなりません。 また、対応するタグファイルを移動するのに、larch moveコマンドを使わな くてはなりません。これは実績のある方法ですが、ユーザによっては、 add, delete, や move のような コマンドを使うのを不便に思う人もいます。

タグづけの暗黙的な方法 暗黙的な 方法は、明示的な方法と、 名前による方法のスーパーセットです。 特定のファイルに対して、タグを定義しないこともできます — その場合、名前による方法のように扱われます。 larch addを使ってタグを定義することもできます — この場合、 明示的な方法のように扱われます。しかし、 暗黙的な方法の本当の便利さは、次のような ものです: そのファイルの先頭または末尾付近に特殊な形式の文字列を埋め込むことに よってファイルにタグを定義することもできます (たとえば、ソースファイルのコメント部分などに)

新規ユーザにとっては一番馴染みのない方法であるとは思いますが、 暗黙的な 方法を使うことを強く進めます。 以下で見ていくように、それは、欠点を十分に補うだけの利点があります。

タグづけの方法の設定

ツリーのタグづけ方法の設定や確認のためには tagging-method コマンドを使います:

        % cd ~/wd/hello-world

        # set the tagging method
        # 
        % larch tagging-method implicit


        # check the tagging method
        # 
        % larch tagging-method
        implicit

タグづけの方法の設定時に有効な値は、names, explicit, そして implicit のどれかです。

名前によるタグづけの利用

名前による タグづけを使いたいのなら、以下のようなコマンドを使います:

        % larch tagging-method names

このコマンドの後では、すべてのファイルはツリーのルートからの相対的な パスから作られるタグを持つようになります。

(繰り返しになりますが、名前による タグづけの方法は、 ファイルが名称変更された場合にチェンジセットがきれいに働かないという 欠点があることに注意してください)

明示的なタグづけの方法の利用

明示的な タグづけの方法を使いたい場合は以下のようなコマンドを使います:

        % larch tagging-method explicit

明示的な 方法を使う場合、(普通は)すべてのファイルとディレクトリ に対してlarch addを使ってタグを付ける必要があります:

        % larch add FILE

もしFILE がディレクトリなら、それは FILE/.arch_ids/=id を作ります。もし通常のファイルであるか、シンボリックリンクである場合は、それは(同じディレクトリ 内に).arch_ids/FILE.idを作ります。どちらの場合でも、その作成されたファイルには ファイル対する自動的に生成されたタグを含んでいます。

通常のファイルやシンボリックリンクを削除する時には、以下のコマンドを利用しなくては なりません:

        % larch delete FILE

これは FILE 自身を削除することはありませんが、 FILE の目録タグを削除します。

ディレクトリを削除するには、.arch_idsサブディレクトリを自分で 削除しなくてはなりません。これはまた暗黙的に、そのディレクトリに保管されている archが押えていた全てのファイルの目録タグを削除します。 (たとえば、ディレクトリを削除するためのrm -rfの利用は、そのタグも 削除します。)

通常のファイルやシンボリックリンクを名称変更する場合に、以下のコマンドを使うと:

        % larch move OLD-NAME NEW-NAME

そのファイルの目録タグが移動します。

利用にあたっての注意: larch moveは、unix のmvのようには働きません。 特に NEW-NAME はファイル名でなくてはなりません — ファイルが移動する先のディレクトリの名前であってはなりません。

ディレクトリを名称変更する場合、その目録タグ(とそのディレクトリに 含まれるすべてのファイルとサブディレクトリのタグ)はそれと一緒に自動的に 移動します (理由は、.arch_ids サブディレクトリが移動されるからです)。

明示的なタグづけした作業ディレクトリ中で larch inventory を実行 すると、明示的に選ばれたソースファイルだけが一覧表示されます。 ソースファイルの名前規約に渡された全てのファイルの一覧を見たい場合には 以下のようなコマンドを使います:

        % larch inventory --source --names

tree-lint についても読んでください。( 物事を単純に保つこと項参照).

暗黙的な目録の利用

暗黙タグを利用する場合は、プロジェクトツリー中で以下のコマンドを 使ってください:

        % larch tagging-method implicit

この方法では: タグが割り当てられていないファイルはすべて、 その位置に基づいたタグが割り振られます — それは 名前による 方法の場合と一緒になります。larch addで割り当てられたタグをもつ ファイルは、そのタグを使います — それは明示的な方法の 場合と一緒になります。しかし、さらに、ファイルの先頭または末尾付近に特殊な形式の 文字列を追加することによってファイルにタグづけすることもできます。

ファイル中に埋め込む形のタグは、ファイルの先頭または末尾の1024バイト 以内に現れる一行で、以下の形をしています:

        <punct>tag:<spaces><tag>

例えば:

        /* tag: main for the hello world program
         */

注意: 目録タグの先頭または末尾の空白はタグの一部とは みなされません。タグ中で、表示できない文字は_で置き換えられます。 例えば、以下のようなタグを書いた場合:

        main for the hello    world program

実際の目録タグは以下のようになります:

        main_for_the_hello____world_program

物事を単純に保つこと

以下のようなコマンド:

        % larch tree-lint

は、物事を単純に保つのに役にたちます。

明示的な タグづけの方法を使っているなら、 上記のコマンドは、どのファイルにも対応しないタグがどれであるかを 教えてくれます。それは、名前による規約を破りはしないが、明示的なタグは存在しない ようなファイルを教えてくれます。

もし暗黙的な タグを使う場合は、タグが見つからないすべてのファイル について教えてくれます — 明示的なタグ、暗黙的なタグの両方についてです。 また、明示的なタグでファイルに対応していないものについても教えてくれます。

どちらの場合でも、あるいは、名前による タグづけの方法を使った 場合でも、tree-lint は、名前による規約に合致しないすべてのファイル について教えてくれます。

最後に、もし、明示的なまたは暗黙的なタグを使っている場合、 tree-lint は複数のファイルで同じタグを使っているものをチェックします。もし二つのファイルが同じタグを 使っている場合、タグを編集するか(もしファイル自身の中にある場合)、重複している明示的な タグを置き換えるためにdeleteaddコマンドを使って 修復しなくてはなりません

hello-world プロジェクトのタグづけ

以前までの章でやってきた例の続きです:hello-worldプロジェクトに 暗黙的なタグづけの方法を使ってみましょう:

        % cd ~/wd/hello-world

        % larch tagging-method implicit

さて、tree-lint は、何を報告するでしょうか?

        % larch tree-lint
        [...]
        ** WARNING: untagged files
        
           This directory uses the "implicit" inventory method, but
           these files do not have either implicit or explicit tags.
        
        *** file-list
        
                ./hw.c
                ./main.c

タグを追加するためにソースファイルを編集すると、:

        % tail -3 main.c
        
        /* tag: main module of the hello-world project
         */
        % tail -3 hw.c
        
        /* tag: hello_world module of the hello-world project
         */

それから、tree-lint を実行すると警告は出なくなります。

利用に関する注意 1: {arch}中のどのファイルにもタグをつけなかったことに注意して ください。arch はすべての制御ファイルに暗黙的なタグを用意 します。

利用に関する注意 2: 今回の小さなサンプルプロジェクトではarchコントロールディレクトリ 以外のサブディレクトリはありません。もしそのようなサブディレクトリがある場合は、 それに対してlarch addでタグを付けたいと思うかも知れません。

ファイルにタグづけする他の方法

ある状況では、全てのファイルに明示的なタグをつけたり、暗黙的なタグをつけたりする のが不便なことがあります。

あるディレクトリ中のファイルに明示的なタグをつけないような場合に、 "デフォルトのタグ"を設定することができます。以下のようなコマンドを使います:

        % larch explicit-default TAG-PREFIX

この後では、そのディレクトリ中のファイルで明示的なタグがついていないものにも タグが割り当てられます:

        TAG-PREFIX__BASENAME

ここで BASENAME はファイルのベース名です。 この方法で作られたデフォルトタグは、ファイルに埋め込まれた暗黙的なタグに 優先します。あるディレクトリのデフォルトタグを確認するには:

        % larch explicit-default
        TAG-PREFIX

そしてそのデフォルトを削除るすには:

        % larch explicit-default --delete

また、暗黙的なタグよりも低い優先順位を持ったデフォルトタグを指定する こともできます:

        % larch explicit-default --weak TAG-PREFIX

そしてそのデフォルト値を表示するには:

        % larch explicit-default --weak

あるいは削除する場合は:

        % larch explicit-default --weak --delete

tree-lint を黙らせること

暗黙的なタグを使っているとき、タグづけされていない(明示的に、または暗黙的に)たくさんの ファイルがあるディレクトリがあるのだが、そのようなファイルをtree-lint によって生成されるタグづけされていないファイルとして報告して欲しくないことがあります。 そのようなファイルにたいしてtree-lintを黙らせるための二つの方法が あります。

ひとつは、デフォルトの明示的なタグあるいは、弱いデフォルトの明示的なタグを 前に説明したlarch explicit-defaultを使って用意することです。

もう一つの方法は、「無視」というラベルをそのディレクトリに付与することです — そのラベルは、tree-lint がタグづけされていないファイルについて不平を言わない という意味をもつものです。そうするには:

        % larch explicit-default --dont-care set

あるいは、「無視」フラグを削除するには:

        % larch explicit-default --delete --dont-care

あるディレクトリに「無視」フラグが設定されているかどうか を知るためには:

        % larch explicit-default --dont-care

第11章 最初のリビジョンのインポート

復習: もし、前の章までの例をたどってきたのなら、以下のようなものが できているはずです:

自分のarch ユーザID 第5章 archが自分自身を識別するために使うID文字列を設定します。

最初のアーカイブ 第6章 最初のアーカイブを作って、それをデフォルトアーカイブとしました。 第7章 そのアーカイブにhello-worldプロジェクトを追加しました。

最初のソースツリー 第8章 archのプロジェクトツリーとして、hello-worldのソースコートを 初期化し、 そして、 第10章 そのプロジェクトのソースファイルに目録タグを割り当てました。

さて、アーカイブにhello-worldのソースをいんポートする 最後の 瞬間がやってきました。 これには二つのステップがあります: (1) ログメッセージの作成と (2) ソースのインポートです。

最初のログファイルの作成

アーカイブに、新しいhello-worldの"リビジョン"をいままさに作ろうとして いるところです: リビジョンとは、そのプロジェクトがある特定の時点でどのように見えるか という記録のことです。

新しいリビジョンを作るときは常に、そのリビジョンについてのログファイルを 作ります。

        % cd ~/wd/hello-world

        % larch make-log
        ++log.hello-world--mainline--0.1--lord@emf.net--2003-example

このコマンドからの出力は、いま編集しなくてはならないファイルの名前です。 初期状態では、それは以下のものを含んでいます:

        Summary: 
        Keywords: 

このファイルに、ちょうど emailメッセージのような内容を埋めてやる必要があります。 Summary:フィールドのリビジョンについての短い記述を追加し、 本体に詳細な記述を追加します。emailと同様、本体は空行でヘッダーと分ける必要が あります。これが終った時点で、ログは以下のような形になります:

        Summary: initial import
        Keywords: 

これはhello-worldの最初のインポートで、この驚異的なプログラムは 私たちの新しい .com カンパニーを飛躍させるものになるでしょう。

vi ユーザに対しての注意: ログメッセージのデフォルトのファイル名称は+ で始まります。viは、+で始まる 引数を、普通の引数と考えず、オプションとして扱うという意味で 非標準的なプログラムです。そのため、viにファイル 名称を渡すことを確実にするために、./で始めて ください。以下のような感じです:

    % vi ./++log.hello-world--mainline--0.1--lord@emf.net--2003-example

(今後、ログファイルのデフォルト名称を変更する予定があり、そうなれば ./ は不要になります。)

アーカイブ中への最初のリビジョンの保存

最後に arch に対してアーカイブにソースを追加するように 指示することができます:

        % larch import
        [....]

いくつかの方法で、このコマンドの副作用を見ることができます。

ます、今回のプロジェクトについて、アーカイブ中に どのようなリビジョンが存在しているかを arch に問い合わせることが できます:

        % larch revisions hello-world--mainline--0.1
        base-0

実際にはもっと詳細情報を得ることもできます:

        % larch revisions --summary --creator --date \
                          hello-world--mainline--0.1 
        base-0
            2003-01-28 00:45:50 GMT
            Tom (testing) Lord <lord@emf.net>
            initial import

プロジェクトツリー中で何が変更されたのでしょうか? "パッチログ"と呼ばれるものがあるのを思い出してください:

        % larch logs
        lord@emf.net--2003-example/hello-world--mainline--0.1

いまの場合それは、以下のエントリーを持ちます:

        % larch log-ls hello-world--mainline--0.1
        base-0

        % larch log-ls --summary --creator --date \
                       hello-world--mainline--0.1
        base-0
            2003-01-28 00:45:50 GMT
            Tom (testing) Lord <lord@emf.net>
            initial import

        % larch cat-log hello-world--mainline--0.1--base-0
        Revision: hello-world--mainline--0.1--base-0
        Archive: lord@emf.net--2003-example
        Creator: Tom (testing) Lord <lord@emf.net>
        Date: Mon Jan 27 16:45:50 PST 2003
        Standard-date: 2003-01-28 00:45:50 GMT
        Summary: initial import
        Keywords: 
        New-files: ./hw.c ./main.c
        New-patches: \
          lord@emf.net--2003-example/hello-world--mainline--0.1--base-0

        This is the initial import of hello-world, the killer app
        that will propel our new .com company to a successful IPO.

インポートからのリビジョン名

import はアーカイブ中に新しいリビジョンを作ります。 作成されたリビジョンはbase-0と呼ばれますが、カテゴリ、 ブランチ、そしてバージョン名を付けてそのリビジョンのもっと長い名前を 作ることもできます。

        hello-world--mainline--0.1--base-0
        ^^^^^^^^^^^  ^^^^^^^^  ^^^  ^^^^^^
             |          |       |     |
             |          |       |    patch level name
             |          |       |
             |          |     version number
             |          |
             |     branch name
             |
         category name

アーカイブ名を追加する場合、"完全に修飾されたリビジョン名"とでも言うべき 名前を手に入れることができますが、それは、そのリビジョンの大域的にユニーク な名前になります:

    lord@emf.net--2003-example/hello-world--mainline--0.1--base-0
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
                |
          archive name

完全な修飾名は後の章で分散リポジトリに関して学ぶにつれて、 その重要性を増していきます。

どのように働くか — インポートの効果

import がアーカイブに与える効果について見てみましょう:

        # cd to the directory for the version we are working 
        # on:
        # 
        % cd ~/{archives}
        % cd 2003-example/
        % cd hello-world/
        % cd hello-world--mainline/
        % cd hello-world--mainline--0.1/
        % ls
        % ls
        +version-lock   =README         base-0

それは、リビジョンのために新しい base-0 ディレクトリを作ります。

        % cd base-0
        % ls
        +revision-lock
        hello-world--mainline--0.1--base-0.src.tar.gz
        log

+revision-lock ファイルは常にarchがどのような状況に おいても一貫した状態をとり続けるために内部的に利用されます。

log ファイルは、自分が付けたログメッセージのコピーに いくつかの追加ヘッダーをつけくわえたものです:

        % cat log
        Revision: hello-world--mainline--0.1--base-0
        Archive: lord@emf.net--2003-example
        Creator: Tom (testing) Lord <lord@emf.net>
        Date: Mon Jan 27 16:45:50 PST 2003
        Standard-date: 2003-01-28 00:45:50 GMT
        Summary: initial import
        Keywords: 
        New-files: ./hw.c ./main.c
        New-patches: \
          lord@emf.net--2003-example/hello-world--mainline--0.1--base-0

        This is the initial import of hello-world, the killer app
        that will propel our new .com company to a successful IPO.

最後に圧縮された tar ファイルは、プロジェクトツリーにあるソースファイルの コピーです:

        % tar ztf hello-world--mainline--0.1--base-0.src.tar.gz
        hello-world--mainline--0.1--base-0/
        hello-world--mainline--0.1--base-0/hw.c
        hello-world--mainline--0.1--base-0/main.c
        hello-world--mainline--0.1--base-0/{arch}/
        hello-world--mainline--0.1--base-0/{arch}/.arch-project-tree
        hello-world--mainline--0.1--base-0/{arch}/=tagging-method
        hello-world--mainline--0.1--base-0/{arch}/hello-world/
        [....]

tar ファイルはプロジェクトツリー中のすぺてのファイルを含んでいるわけで はないことに注意してください。それは、以下のコマンドで一覧表示されるファイルを含んでいます:

        % cd ~/wd/hello-world

        % larch inventory --source --both --all
        [....]

最後に、プロジェクトツリーの {arch} サブディレクトリをのぞいてみると、 二つの新しいアイテムができていることに気づくと思います:

        % ls
        ++default-version       =tagging-method
        ++pristine-trees        hello-world

ディレクトリ ++pristine-trees は、インポートされたツリーのコピー (ある深さの) を含んでいます。これは、他のarchコマンドによって利用される キャッシュコピーです。(archの今後のリリースでは、 ++pristine-trees サブディレクトリは別の仕組みによって置き換えられるかも 知れません。)

hello-world (パッチログ)ディレクトリの周辺をのぞいてみると、 今作ったばかりのリビジョンのログファイルのコピーを見つけることができます( 追加のヘッダーが付け加えられた形で見えます)。

第12章 修正点のチェックイン

いままで、もし例に沿って読んできたのなら、新しいアーカイブが作成されている はずで、そのアーカイブ中にはhello-world プロジェクトがあり アーカイブ中にはhello-world の最初のバージョンがインポート されているはずです。

リビジョン管理システムを使ってプログラムを作る上で、一番普通に実行される のは、ひとまとまりの変更点の"コミット"です。この章では、それが動作する 一番基本的な方法について見ていきます。

warld != world

hello-world のソースコードを見れば、スペルミスと、改行バグがあるのが わかるはずです:

        % cat hw.c

        #include <stdio.h>

        void
        hello_world (void)
        {
          (void)printf ("hello warld");
        }

        
        /*tag: hello_world module of the hello-world project
         */

明らかにhello warld ではなく、hello worldと出力したい わけですし、多分メッセージの最後では改行を出力するのが普通でしょう。それでこれらのバグを 修正しましょう。

ログメッセージについてのいくつかのアドバイス

* *Free advice is worth what you pay for it.* -- anonymous.

これらのバグを修正するための計画があります: 私たちはソースを修正してこのバグを直します。 それからarch に、アーカイブ中のバグを修正するのに必要な変更を記録する ように言います。二番目のステップは新しいリビジョンをアーカイブに 作ります。

前に言ったように、新しいリビジョンを作るときはいつでもそのリビジョンのための ログメッセージ を用意する必要があります。 最初のログファイルの作成項

今回の簡単な例で直そうとしているバグは非常につまらないものです — しかし、現実の状況では、それはもっと複雑なものになりえます。あなたは 選ぶことができます: あなたの修正点を説明するログメッセージを書くために すべての変更が終了するまで待つこともできますし、ログメッセージだけを書いて おくこともできます。

アドバイス: ログメッセージだけを書きましょう。言い換えると、ハックしたつど、 記録をとりましょう。larch コマンドでは、それは、バグ修正 の処理を以下のコマンドで始めることを意味します:

        % cd ~/wd/hello-world

        % larch make-log
        ++log.hello-world--mainline--0.1--lord@emf.net--2003-example

それから新しいログファイルを編集するのに、以下を読み込みます:

        Summary: Fix bugs in the "hello world" string
        Keywords: 

Summary: はこれからやる変更に関連したものとしての説明になります。 作業をすすめるたびに、ログメッセージの変体に記録をとっていきます。

編集/ログ更新のサイクル

これらのバグは実際よりも複雑であるとします。この場合作業がどのように進むかを 説明します:

スペルミスの修正。warldworldに修正。 ログメッセージの更新。 ログファイルに記録を追加:
        Summary: Fix bugs in the "hello world" string
        Keywords: 

        Spell "world" correctly (not "warld").
改行エラーの修正。 メッセージに改行を追加。 ログメッセージをもう一度更新。 ログファイルに記録を追加:
        Summary: Fix bugs in the "hello world" string
        Keywords: 

        Spell "world" correctly (not "warld").

        Add a newline to the hello world message.

ああ、なんてこと — いったい何をしてしまったんだ?

そしてこのような複雑なバグフィックスのために長くハードな作業を し終えたとします。公開する前に、もう一度、作業の見直しをするのは 良い考えではないでしょうか? 大丈夫。arch がお手伝いします:
        % larch what-changed --diffs
        [....]
        *** patched regular files
 
        **** ./hw.c
        [....] 
             @@ -4,7 +4,7 @@
              void
              hello_world (void)
              {
             -  (void)printf ("hello warld");
             +  (void)printf ("hello world\n");
              }
        [....]
なるほどね。さあこれでアーカイブに変更を保存することができますね。

アーカイブへの変更点の保存

さあ、アーカイブに変更点を保存しましょう。 もし、私達のアドバイスを聞き入れていなかったのなら (see "Some Free Advice About Log Messages"), ここでログメッセージを作る必要があります。 (hint: use `larch make-log'). アーカイブに変更を保存するには、単に以下のようにします:
        % larch commit
        [....]
commit が完了すると、アーカイブには新しいリビジョンができます:
        % larch revisions hello-world--mainline--0.1
        base-0
        patch-1
あるいはもっと詳細を知りたいなら:
        % larch revisions --summary hello-world--mainline--0.1
        base-0
            initial import
        patch-1
            Fix bugs in the "hello world" string
プロジェクトツリーのパッチログも同様に更新されます:
        % larch log-ls hello-world--mainline--0.1
        base-0
        patch-1

        % larch log-ls --summary hello-world--mainline--0.1
        base-0
            initial import
        patch-1
            Fix bugs in the "hello world" string

どのように動作するか — 新しいリビジョンのコミット

commit はアーカイブに対して何をするのでしょうか?
        # cd to the directory for the version we are working 
        # on:
        # 
        % cd ~/{archives}
        % cd 2003-example/
        % cd hello-world/
        % cd hello-world--mainline/
        % cd hello-world--mainline--0.1/
        % ls
        % ls
        +version-lock   =README         base-0          patch-1
patch-1 サブディレクトリは新しく作られたものです:
        % cd patch-1

        % ls
        +revision-lock
        hello-world--mainline--0.1--patch-1.patches.tar.gz
        log
普通、ログファイルは、あなたの書いた内容に、いくつかの追加ヘッダを 付け加えたものです:
        % cat log
        Revision: hello-world--mainline--0.1--patch-1
        Archive: lord@emf.net--2003-example
        Creator: Tom (testing) Lord <lord@emf.net>
        Date: Mon Jan 27 22:26:13 PST 2003
        Standard-date: 2003-01-28 06:26:13 GMT
        Summary: Fix bugs in the "hello world" string
        Keywords: 
        New-files: \
          {arch}/hello-world/ [....] /patch-log/patch-1
        Modified-files: hw.c
        New-patches: \
          lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1

        Spell "world" correctly (not "warld").

        Add a newline to the hello world message.

.patches.tar.gz ファイルは、何か チェンジセットと 呼ばれるようなものです。それはbase-0と、patch-1のリビジョン間 の差分として、あなたの変更点を記述したものです。後の章でチェンジセットの性質についてもっと詳しく 学ぶことになるでしょう。いまは、チェンジセットを、あなたが変更を加える前のbase-0 リビジョンと変更を加えたあとの、同じツリーとの間で実行したdiff -rの出力と 同様のものとしてとらえることができます。 (あるいは、arch ユーザの一人によれば: ステロイド上のパッチセット、となります)

プロジェクトツリー中で:
        % cd ~/wd/hello-world

コミットコマンドは二つの効果を持ちます。一つは、 {arch}/hello-world配下に、ログファイルを追加します。第二に、base-0 リビジョンの代わりに、patch-1リビジョンのキャッシュコピーを含むように、 {arch}/++pristine-trees を書き換えます。

第13章 以前のリビジョンの抽出

前の章までの例にそって読み進めてきたのななら、以下のようなものができて いるはずです:

あなたの最初のアーカイブ それはまたあなたの デフォルトのアーカイブでもあります:

        % larch my-default-archive
        lord@emf.net--2003-example

        % larch whereis-archive lord@emf.net--2003-example
        /usr/lord/examples/{archives}/2003-example

アーカイブ中にできているhello-worldプロジェクト

        % larch categories 
        hello-world

        % larch branches hello-world
        hello-world--mainline

        % larch versions hello-world--mainline
        hello-world--mainline--0.1

hello-world プロジェクトのふたつのリビジョン

        % larch revisions hello-world--mainline--0.1
        base-0
        patch-1

この章では、アーカイブからどのようにしてリビジョンを取り出すかについて 学びます。

最後のリビジョンのチェックアウト

まだプロジェクトツリーが残っているかも知れません。その場合は、それを いったん削除してください:

        % cd ~/wd

        % ls
        hello-world

        % rm -rf hello-world

hello world プロジェクトの最後のソースを手にいれたいとしましょう。 それには、get コマンドを使います:

        % larch get hello-world--mainline--0.1 hello-world
        [...]


        % ls 
        hello-world

        % ls hello-world
        hw.c    main.c  {arch}

もっと以前のリビジョンのチェックアウト

hello-world のもっと前のバージョンをチェックアウト したいとしましょう。

前の例では、プロジェクトの特定のバージョンを要求したことに注意してください:

        % larch get hello-world--mainline--0.1 hello-world
                    ^^^^^^^^^^^  ^^^^^^^^  ^^^ ^^^^^^^^^^^
                         |           |      |       |
                         |           |      |  target directory
                         |           |      |
                         |           |      |
                         |           |   version number
                         |           |
                         |      branch name
                         |
                   category name

patch level を明示的に指定することで、もっと以前のリビジョンを 手にいれることができます:

        % larch get hello-world--mainline--0.1--base-0 hello-world-0
                    ^^^^^^^^^^^  ^^^^^^^^  ^^^  ^^^^^^ ^^^^^^^^^^^^^
                         |           |      |      |        |
                         |           |      |      |  target directory
                         |           |      |      |
                         |           |      | patch level name
                         |           |      |
                         |           |   version number
                         |           |
                         |      branch name
                         |
                   category name




        % ls
        hello-world     hello-world-0

        % ls hello-world-0
        hw.c    main.c  {arch}

base-0 から patch-1 になされた変更点を見ることができます。 たとえば、diff -rを使えばできます:

        % diff -r hello-world-0 hello-world
        diff -r hello-world-0/hw.c hello-world/hw.c
        7c7
        <   (void)printf ("hello warld");
        ---
        >   (void)printf ("hello world\n");
        [...]

どのように動作するのか — get を使ったリビジョンの抽出

base-0 リビジョンを抽出するのは簡単です。思い出すことができるように、 base-0 リビジョンは、完全なソースツリーの圧縮された tar ファイルとして 保存されています( どのように働くか — インポートの効果項参照)。 base-0の抽出を指示すると、getコマンドは本質的には 単にその tar ファイルを展開するだけです。

patch-1 リビジョンの抽出は、二つのステップで実行されます。 patch-1base-0patch-1 の間の差分を記述したchangeset として保存されていることを思い出して ください。(どのように動作するか — 新しいリビジョンのコミット項参照)。 それで get は、最初にbase-0リビジョンを抽出し、 次にpatch-1を抽出し、そのチェンジセットをbase-0を 変形するのに利用することで、patch-1のツリーに変化します。 内部的には、get は、larchのコマンド、dopatch を チェンジセットを適用するのに使います。もし、diff/patchパッチセットに なじみがあるのなら、dopatch を、「ステロイドの上へのパッチ」 と考えることもできます。

ひとつの変更をコミットするかわりに、たくさんの変更をコミットしたとしましょう: patch-1 のリビジョンだけではなく、 patch-2, patch-3 などなど。本質的には getは、要求したリビジョンを 作るために、それぞれのチェンジセットを適用します。

注意: 実際には get は、上に説明したよりも、もう少し複雑なことをします。 たくさんのチェンジセットを適用しなくてはならないことを考慮して、get は最適化されています。一方、commitではなく、tagによって 作られたリビジョンもあるかも知れません。その場合は別の規則が適用されます。後の章でこの例外 について学ぶでしょう。

第14章 共有アーカイブと、公開アーカイブ

前の章で、どのようにして最初のアーカイブを作り、プロジェクトを始め、 最初のソースをチェックインし、一連の変更を加え、過去のリビジョンを抽出 するかについて学びました。

この章では、ネットワーク越しに利用できるアーカイブをどうやって作るかについて 学び、どうやって一つのアーカイブを複数のプログラマ間で共有することができるかに ついて学びます。

アーカイブのネットワークアクセス登録

思いだすことができると思いますが、アーカイブは、論理名と物理位置を持って いるのでした:

        % larch archives
        lord@emf.net--2003-example
        ^^^^^^^^^^^^^^^^^^^^^^^^^^
          |     /usr/lord/{archives}/2003-example
          |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          |                     |
          |              archive location        
          |
        archive name

(See xref:"Creating a New Archive".)

いくつかのアーカイブはネットワーク越しにアクセスすることができ、 現在のところ、以下のプロトコルが利用可能です:

        FTP
        SFTP
        WebDAV
        plain HTTP

この章の後のほうで、どうやってそのようなアーカイブを作るかについて 学びます。

いまは、そのようなアーカイブにアクセスするためには、そのアーカイブの名前と URLを使って表現された物理位置を登録する必要があるということを知っておいてください。

例えば、 HTTP か WebDAV を使ってアーカイブにアクセスするには:

    % larch register-archive lord@emf.net--2003 \
            http://regexps.srparish.net/{archives}/lord@emf.net--2003

FTPを使うなら:

    % larch register-archive lord@regexps.com--2002 \
            ftp://ftp.regexps.com/{archives}/lord@regexps.com--2002

このようなコマンドがうまくいったかどうかを確認することができます:

    % larch archives
    lord@emf.net--2003
            http://regexps.srparish.net/{archives}/lord@emf.net--2003
    lord@emf.net--2003-example
            /usr/lord/examples/{archives}/2003-example
    lord@regexps.com--2002
            ftp://ftp.regexps.com/{archives}/lord@regexps.com--2002

一度に複数のアーカイブを使った作業

追加のアーカイブを登録した後、どのようにそれにアクセスすれば良いのでしょうか?

単純なやりかたとしては、そのアーカイブをデフォルトに設定してしまう というのがあります:

        % larch my-default-archive lord@emf.net--2003

        % larch categories
        [...categories in the remote archive...]

デフォルトアーカイブを変更するのは、もちろん不便です。 そこで、例で使っていたアーカイブをデフォルトに戻しておきます:

        % larch my-default-archive lord@emf.net--2003-example

リモートアーカイブにアクセスするには他に二つの方法があります:

アーカイブを -A オプションで選択する

アーカイブ上の操作をするすべてのコマンドは -A オプションを受け入れますが これはデフォルトアーカイブを上書きするために使うことができます:

        % larch my-default-archive
        lord@emf.net--2003-example

        % larch categories -A lord@emf.net--2003
        [... categories in lord@emf.net--2003 ...]

利用についての注意: -A 引数は、デフォルトアーカイブよりも優先順位が高いですが、 完全に修飾されたプロジェクト名称によってさらに上書きされてしまいます (以下を参照)。

完全に修飾されたプロジェクト名

プロジェクト名を受け入れるコマンドは、"完全に修飾されたプロジェクト名" を使うことができます。完全に修飾された名前は、アーカイブ名称を接頭辞とし、 スラッシュが続き、その後にプロジェクト名を続けたものです:

   category name:
   arch                     => lord@emf.net--2003/arch

   branch name:
   arch--devo               => lord@emf.net--2003/arch--devo

   version name:
   arch--devo--1.0          => lord@emf.net--2003/arch--devo--1.0

   revision name:
   arch--devo--1.0--patch-1 => lord@emf.net--2003/arch--devo--1.0--patch-1

この例では:

        % larch my-default-archive
        lord@emf.net--2003-example

        % larch branches lord@emf.net--2003/arch
        [... branches of arch in lord@emf.net--2003 ...]

利用にあたっての注意: 完全に修飾された名前は、-Aオプションと、 デフォルトアーカイブのどちらにも優先します。

読み込み専用アーカイブ

オペレーティングシステムとサーバアクセス制御は読み込み専用アクセス に対して、数人またはすべてのユーザを制限するために利用することができます。 例えば、FTPは普通、匿名ユーザに読み込みを許しますが、アーカイブの修正は許しません。

読み込み専用のアーカイブのミラー

互換性についての注意: この節で記述されるしくみは、今後のリリースでは変更されるかも知れません。ミラーは もっときれいな形でサポートされるでしょう。しかし、このしくみは、作業する上で 「十分うまく」動作しているので、現在のところ広く利用されています。

arch のよくある使い方は、ローカル(つまり、ネットワークアクセスできない )アーカイブで、普通の作業をし、"アーカイブミラー"を作ることによってネットワーク上に そのアーカイブを"公開"することです。

ミラーは以下のようにして作ります:

1) 初期状態として空のネットワークアクセス可能なアーカイブを作ります。 2) リモートアーカイブのルートの、=meta-dataディレクトリに、=mirror と呼ばれるファイルを保管します。このファイルは、一行のみを含んでいるべきです: それは、ミラーされるアーカイブの名前です。 3)larch push-mirror コマンドを使って、 ローカルアーカイブのデータをミラーにコピーします:
    % larch push-mirror lord@emf.net--2003 lord@emf.net--2003-mirror
    [....]

利用に関する注意: ユーザは push-mirror コマンドを手で実行してはいけません。 そのかわり、以前コピーしたアーカイブの部分についての記録をとることによってpush-mirror を最適化するnotifierと呼ばれるものを作ります。 notifier については、後の章でより詳しく学びます ( 第29章参照)。

利用についての注意: ネットワーク越しにアクセス可能なミラーについて他の人に公開する場合、 あなたのlocalなアーカイブの名前でそのミラー を登録するように言ってください。リモートユーザに関する限り、そのミラーは あなたのローカルアーカイブと同じものです。

混合アクセスモード

複数のアクセス方法を経由することができるような一つのアーカイブを作る ことを防げることは何もありません。例えば、FTPのディレクトリを含むような マシン上のローカルファイルシステムの場所を使ってアクセスできるFTPアーカイブ を登録することもできますが、その同じアーカイブを、別の人には ftp: 形式のURLとして登録することもできます。

FTP アーカイブの作成

アーカイブは、FTPサーバが利用できるような場所の中にあるディレクトリの どこかに単に配置するだけで、FTPアクセス可能となります。

セキュリティーに関する注意: FTPアクセス可能なアーカイブを作る場合、二つの重要なセキュリティ上の考慮が必要になります: 平文でのパスワードと、 FTP サーバの設定です。

平文でのパスワード よく知られているように、FTPプロトコルはパスワードを、暗号化せずにネットワーク上を 流します。多くの場合、それは受け入れられないセキュリティリスクと考えられる ので、FTPアクセスは、公開データのみに利用し、読み込み専用アクセスとすべきかも 知れません。

FTP サーバの設定 一般的に言って、FTPサーバを十分セキュアに設定するには、オペレーティングシステムと 利用するFTPサーバの実装についての関連したドキュメントを注意深く、十分に理解する 必要があります。

SFTP アーカイブの作成

[これはまだドキュメント化されていません]

WebDAV と HTTP アーカイブ

[これはまだドキュメント化されていません]

第15章 update/commit スタイルの共同作業

前の章までで、どうやってアーカイブにプロジェクトを追加し、 最初のソースを保管し、そのようなソースに加えた変更を保管し、 そのアーカイブからリビジョンを抽出するかについて学んできました。

前の章では、どうやってアーカイブをネットワーク越しにアクセス可能にするか を学びました。

この章では、どのようにして特定のプロジェクトに対してお互いに変更を加えるような 複数のプログラマーが、一つのアーカイブを共有することができるかについて話しを進めていきます。

アーカイブを共有したり、与えられたプロジェクト上で共同作業する方法には それぞれ微妙に違った非常にたくさんの方法があるということを知って置く必要 があります。その中で、 一番簡単なテクニックの一つから 始めます。

アリスとボブは main をハックします

アリスとボブの両者がhello-worldプロジェクト上で作業し、 一つのアーカイブを共有しているとしましょう。我々の例では、両方の役割を同時に こなすことにします。

最初に、両方のプログラマーはそれぞれ自分自身のプロジェクトツリーが必要に なります。

        % cd ~/wd

        % [ ... remove any directories left from earlier examples ...]


        % larch get hello-world--maineline--0.1  hello-world-Alice
        [....]

        % larch get hello-world--maineline--0.1  hello-world-Bob
        [....]

アリスのタスクは、それぞれのファイルに、いくつかの合理的な注釈を付け加える ことです。それが終った時点で(しかし、アーカイブにはまだ変更をcommit していないという前提では)ファイルは以下のようになっています:

        % cd ~/wd/hello-world-Alice

        % head -3 main.c
        /* Copywrong 1998 howdycorp inc.  All rights reversed.*/

        extern void hello_world (void);

        % head hw.c
        /* Copywrong 1998 howdycorp inc.  All rights reversed. */

        #include <stdio.h>

一方ボブは、mainに、もっと多くのコメントを追加していたとします:

        % cd ~/wd/hello-world-Bob

        % cat main.c
        extern void hello_world (void);

        int
        main (int argc, char * argv[])
        {
          hello_world ();

          /* Exit with status 0
           */
          return 0;
        }

        /* tag: main module of the hello-world project
         */

二人のプログラマーは修正されたバージョンのhello-worldを持って いて、両者とも、相手の修正を反映していないことに注意してください。

ボブが先にコミットします

ボブが自分の変更を先にコミットしようとしたとします。 すでにみてきたように、これには二つのステップをとります。

最初にボブはログメッセージを用意します:

   % cd ~/wd/hello-world-Bob

   % larch make-log
   ++log.hello-world--mainline--0.1--lord@emf.net--2003-example

   [Bob edits the log message.]

   % cat ++log.hello-world--mainline--0.1--lord@emf.net--2003-example
   Summary: commented return from main
   Keywords: 

   Added a comment explaining how the return from main
   relates to the exit status of the program.

それからcommitを実行します:

   % larch commit
   [...]

アリスはまだコミットできません

今度はアリスの番です:

   % cd ~/wd/hello-world-Alice

   % larch make-log
   ++log.hello-world--mainline--0.1--lord@emf.net--2003-example

   [Alice edits the log message.]

   % cat ++log.hello-world--mainline--0.1--lord@emf.net--2003-example
   Summary: added copywrong statements
   Keywords: 

   Added copywrong statements to the source files so 
   that nobody can steal HowdyCorp's code.

それからコミットしようとします:

   % larch commit
   [....]
   commit: project tree out of date

     Working directory is missing these patches:

           patch-2

     Unable to complete "commit".

   Try "larch update --help" or "larch commit --out-of-date-ok"

ここでの問題は、ボブの変更はすでにアーカイブに保存されていますが、 アリスのツリーはその変更が反映されていない、というところです。

なぜアリスはコミットすることができないかということについての理解

commit コマンドはアリスに、このツリーが「最新ではない」 ということを伝えます。それは、アリスのツリーがまだコミットする前に、アーカイブに対して 変更がすでにコミットされた、ということを意味します。

彼女はこの状況について、彼女のツリーに何が足りないのかを問い合わせることに よってもう少し深く調べることができます。

        % larch whats-missing
        patch-2

あるいは更に詳細に:

        % larch whats-missing --summary
        patch-2
            commented return from main

それは、ボブのログメッセージからのSummary:行として理解すべき です。

さらに深く調べるためには (以前導入した) revisions コマンドを使うこともできます( アーカイブ中への最初のリビジョンの保存項参照)。

彼女はボブのログメッセージ全体を参照することができます:

    % larch cat-archive-log hello-world--mainline--0.1--patch-2
    Revision: hello-world--mainline--0.1--patch-2
    Archive: lord@emf.net--2003-example
    Creator: Tom (testing) Lord <lord@emf.net>
    Date: Wed Jan 29 12:46:50 PST 2003
    Standard-date: 2003-01-29 20:46:50 GMT
    Summary: commented return from main
    Keywords: 
    New-files: {arch}/hello-world/[....]
    Modified-files: main.c
    New-patches: \
      lord@emf.net--2003-example/hello-world--mainline--0.1--patch-2

    Added a comment explaining how the return from main
    relates to the exit status of the program.

そのメッセージのヘッダを見ることによって、アリスは例えば、 ボブがファイルmain.cを修正したことを知ることが できます。

あとの章で、アリスがボブのした変更について知るために利用できる よりおおくのコマンドについて降れます。しかし今はアリスが どのようにして彼女のツリーにそのような変更を追加することができるか について見てみましょう。

update コマンド

アリスは自分の変更をcommitする前にボブの変更を自分の変更に部分と マージしなくてはなりません。 それをやる簡単な方法のひとつにupdateコマンドを使う方法が あります:

        % cd ~/wd

        % larch update --in-place hello-world-Alice
        [....]

これで彼女はボブの変更を自分のツリーに追加するできます:

        % cd hello-world-Alice

        % cat main.c
        /* Copywrong 1998 howdycorp inc.  All rights reversed. */

        extern void hello_world (void);

        int
        main (int argc, char * argv[])
        {
          hello_world ();

          /* Exit with status 0
           */
          return 0;
        }

        /* tag: main module of the hello-world project
         */

他には変更がない場合には:

        % larch whats-missing
        [no output]
commit はうまく実行できます:
        % larch commit
        [....]

習得にあたっての注意: 例にそって読み進めてきたのなら、ボブの修正は含んでいるが アリスのは含んでいないhello-world-Bobのツリーがあるはずです。 そのディレクトリにたいしていろいろなコマンドを実行してみてください (whats-missing, update, what-changed などなど)。

どのように動作するか — update コマンド

updateコマンドがどのように動作するかについての完全な 説明は、この章の範囲を少し越えています。 いくつかの後の章の後で、updateを詳しく理解することが できるようになるでしょう (チェンジセットとパッチログに関する章です)。

いまは、もし diffpatchになじみがあるのなら、 それをこのような感じで考えることができます:

update がアリスのツリーで実行されると、そのコマンドはpatch-2 リビジョンに向かっているところではあるが、彼女のツリーはpatch-1リビジョンの get としてチェックアウトされたことに気づきます。 update は三段階で動作します:

まず、それは mkpatch というコマンドを利用し、( それはdiffの拡張です) チェンジセットを計算します (パッチセットの拡張です) そのチェンジセットは、アリスが自分のツリーにした変更を記述するものです。

次に、それはpatch-2リビジョンのコピーをチェックアウトして、アリスのツリーを そのリビジョンで置き換えます。

最後に updatedopatch ( patchの拡張です) を使って、最初のステップで作ったパッチセットを 新しいツリーに適用します。

パッチの衝突をどのように扱うか不思議に思うかも知れません。 上の例は、衝突が起こらないように注意して選んだものです。心配する必要は ありません — その話題についてはすぐに触れます (不完全パッチ処理 — どのようにして衝突が扱われるか項 参照)。

第16章 チェンジセット入門

ふたつのプロジェクトツリー(普通は同じプロジェクトになりますが)を比較 して、その間で正確には何が変更されたかを明らかにするのが非常に役に立つこと がよくあります。

チェンジセットは、archの非常に中心的な概念です。— arch の大部分はチェンジセットに関係した操作として定義 されています。

古いツリー」 と 「新しいツリー」 の間のチェンジセットがある場合、 「そのチェンジセットを」 古いツリーに適用して 新しいツリーを得ることができます。— 言い換えると、チェンジセットに 記述されている修正点の編集作業を自動的にやることができます。 もし第三のツリーがあるなら、やはりそのパッチを適用して、第三のツリーに 対しても近似的に同じ変更を得ることができます。

arch はチェンジセットを作ったり適用したりするための 洗練されたツールを用意しています。

mkpatch

mkpatch は二つのツリー間の差分を記述するようなチェンジセットを 計算します。この基本的なコマンドの構文は:

        % larch mkpatch ORIGINAL MODIFIED DESTINATION

これで、ORIGINALMODIFIEDのツリーが比較されます。

mkpatch は新しいディレクトリであるDESTINATIONを作り チェンジセットをそこに格納します。

mkpatch がツリーを比較するときには目録タグを使います。 たとえば、同じタグを持っている場合、その二つのディレクトリや二つのファイルは、 「同じディレクトリ(またはファイル)」 とみなされます — それぞれが、問題のツリーのどの場所にあるかにかかわらず、そうします (第10章 参照)。

mkpatch で作ったチェンジセットはどのファイルやディレクトリが 追加または削除され、どれが名称変更され、どれが修正されたか(そしてどのように修正 されたか)、そして、どのファイルのパーミッションが変更されたか(そしてどのように 変更されたか)を記述します。通常のテキストファイルが比較される場合には mkpatch はその差分を記述するようなコンテキスト diff を生成 します。mkpatch はバイナリファイルを比較したり(違っている 場合は、新旧両方のバージョンの完全なコピーを保存します)、シンボリックリンク を比較したり(両者が違っている場合は、新旧のリンク先を保存します)することも できます。

チェンジセットの形式の詳細な記述については補遺を見てください。 (付録A 参照)。

dopatch

dopatch は、ツリーに対してチェンジセットを適用するのに 使います:

        % larch dopatch PATCH-SET TREE

ツリーが、mkpatchの実行時に現れた 「元の」ツリーそのものである場合、結果はひとつの例外を除いて (これについては以下で説明します)mkpatchの実行時に現れた 「修正された」 ツリーそのものになります。

正確に同じ」 というのは、ディレクトリの構造が同じであり、 シンボリックリンク対象も同じで、通常のファイルの内容、そしてファイルの パーミッションも同じである、ということです。修正時刻、複数のリンクを持つ ファイル、そして、ファイルの所有者に関する情報については、確実に保存 されるとは限りません。

完全に同じ」という規則の例外は、もしパッチがツリー からファイルやディレクトリを削除するようなものである場合、それらのファイルや ディレクトリは、区別できるようなパターンをもった名前で、ツリー のサブディレクトリに保存されるというものです:

        ++removed-by-dopatch-PATCH--DATE

ここで PATCH はパッチセットディレクトリの名前で、DATE はタイムスタンプになります。a

不完全パッチ処理 — どのようにして衝突が扱われるか

dopatchによってパッチされるツリーが mkpatchに現れる元のツリーと完全に同じものではない場合は どうなるのでしょう?

以下は、どうなるかについての概略です。dopatch 処理の完全な ドキュメントは、ソースコード中に含まれています。

dopatch はパッチされるツリーの目録を使います。それは、 チェンジセットによって期待されるどのファイルとディレクトリがツリー中に 存在し、また消えてしまっているかを決定し、それぞれのファイルやディレクトリ がツリー中のどこに位置しているかを明らかにするために目録タグを使います。

単純なパッチ もしチェンジセットが通常のパッチ か、リンク、ディレクトリまたはファイルに対するメタデータのパッチを含んでいて、 そのファイルがツリー中に存在している場合、dopatchはそのパッチ を普通の方法で適用します。もしパッチがきれいに適用されれば、修正されたファイル、 リンク、ディレクトリはその場所に残ります。

もし単純なパッチがきれいに適用できなかった場合は、dopatch は 常に.orig ファイル(変更されることのない、パッチされる 前のツリー中にあったもともとのファイル)と、.rej ファイル(適用 できなかったパッチの一部)を残します。

もしパッチがコンテキスト diff だった場合dopatch はファイルそれ自身 も残します — 一部だけパッチされたものです。

もし (成功しなかった) パッチがバイナリファイルに対するものであった場合、 部分的なパッチのファイルは残されません。その代わり、以下のようになります:

        .orig       -- パッチされるツリーにもともとあったファイルの修正される前の形のもの。

        .rej        -- 修正されたツリーのファイルの完全なコピーで、ファイルパーミッションは
                       .origと同一のもの。

        .patch-orig -- mkpatchに現れた元のツリーからのファイルの
                       完全なコピーで、ファイルパーミッションは元のものを保持した形のもの

                        -であるかまたは-

                       mkpatch に現れた元のツリーからのシンボリックリンク
                       で、パーミッションは元のツリーのもの。

もし (成功しなかった) パッチがシンボリックリンクである場合は、 部分的なパッチファイルは残りません。そのかわり:

        .orig       -- 元のツリーからのファイルで、まだ修正されていないもの。

        .rej        -- パッチの目的となるターゲットへのシンボリックリンクで、
                       パーミッションは .orig からのコピーであるもの。

        .patch-orig -- mkpatchに現れた元のツリーからのファイルの
                       完全なコピーで、パーミッションは元のファイルからのものを保持
                       しているもの

                        -であるかまたは-

                       mkpatchに現れた元のツリーからのシンボリックリンク
                       で、パーミッションは元のツリーのものと同じ。

失われたファイルに対するパッチ

失われたファイルやディレクトリに対するパッチはすべてパッチが 呼び出されたツリーの根元のサブディレクトリ中に保存されます。

        ==missing-file-patches-PATCH-DATE

ここで PATCH はチェンジセットディレクトリのベース名で、 DATE はタイムスタンプです。

ディレクトリの再配置と新しいディレクトリ

ディレクトリはあなたが思っているよりもずっと追加、削除、再配置される もので、実際にはあなたがそれを意識していない場合もあります。

mkpatch が呼び出されたとき、ORIGINAL ツリーが以下のよう だったとしましょう:

        ディレクトリまたはファイル:     タグ:

        a/x.c                           tag_1
        a/bar.c                         tag_2

しかし MODIFIED は以下の形だったします:

        a/x.c                           tag_1
        a/y.c                           tag_2

そして、この両方のファイルには変更が加えられているものとします。 パッチはtag_2 のタグを持ったファイルをy.c に名称変更し、タグtag_1tag_2をもった ファイルの内容を変更したいとします。

たとえば、以下のようなツリーがあり:

        a/foo.c                         tag_1
        a/zip.c                         tag_2

そのツリーにパッチを適用するとします。パッチの後では以下のようなファイル が残り:

        a/foo.c                         tag_1
        a/y.c (was zip.c)               tag_2

パッチは両方のファイルの内容に対して適用されます。

微妙な場合で、衝突をどのように扱うかの例をあげます:

mkpatch に現れる元のツリーが以下のようであるとします:

        ディレクトリまたはファイル:     タグ:

        ./a                             tag_a
        ./a/b                           tag_b
        ./a/b/c                         tag_c

そして修正後のディレクトリは:

        ./a                             tag_a
        ./a/c                           tag_c
        ./a/c/b                         tag_b

最後に、ツリーが以下のようであるとします:

        ./x                             tag_a
        ./x/b                           tag_b
        ./x/c                           tag_new_directory
        ./x/c/b                         tag_different_file_named_b
        ./x/c/q                         tag_c

ツリーにたいしてパッチが適用されると、以下のようになります:

        ./x                             tag_a
                そのパッチは tag_a のディレクトリには
                何も変更しないので。

        ./x/c.orig                      tag_new_directory
        ./x/c.rej                       tag_c
                Since the patch wants to make the 
                directory with tag_c a subdirectory named "c"
                of the directory with tag_a, but the tree
                already had a different directory there,
                with the tag tag_new_directory.

        ./x/c.rej/b                     tag_b
                Since the patch wants to rename the directory
                with tag_b to be a subdirectory named "b"
                of the directory with tag_c.

        ./x/c.orig/b                    tag_different_file_named_b
                Since the patch made new changes to this file,
                it stayed with its parent directory.

第17章 チェンジセットの詳細

前の章ではチェンジセットと、二つのコマンド mkpatchdopatch ( 伝統的なdiffpatch プログラム の魅力的な拡張)を導入しました。

この章ではアーカイブ中でどのようにチェンジセットが利用されるかについてもう少し 詳しく見ていき、commitupdate コマンドによってどのように利用されるか、そして、archを 最大限利用するためにはどのようにすれば良いかについて見ていきます。

どのように動くか — commitはアーカイブ中にチェンジセットを保存します

プロジェクトの最新バージョンをgetし、何かの変更を加え、 ログメッセージを書き、アーカイブにその変更をcommit したと します。これで何が起きるのでしょうか?

本質的に commitのすることは:

1 最新バージョンにどのよう変更をしたかを記述する チェンジセットを計算します。

2 アーカイブ中に新しいリビジョンのためのディレクトリを 作ります。

3 アーカイブ中にログメッセージとチェンジセットを保存します。

そのような観点から、戻って前の章を見たくなるかも知れません: どのように動作するか — 新しいリビジョンのコミット項

get-patch はアーカイブからチェンジセットを取り出します

以前に、cat-archive-log コマンドはアーカイブから ログメッセージを取り出すということを学んだと思います (なぜアリスはコミットすることができないかということについての理解項参照)。

アーカイブからチェンジセットを取り出すこともできます:

        % cd ~/wd

        % larch get-patch hello-world--mainline--0.1--patch-1 patch-1
        [...]

get-patch はアーカイブからチェンジセットを取り出し、 この場合、patch-1という名前のディレクトリに保存して います。

(チェンジセットの形式については 付録A を参照してください)

チェンジセットを調べるためにはpatch-reportを使います

チェンジセットの形式はプログラムによって利用するために最適化されて います。チェンジセットを「そのまま」見るのはとてもやっかい です。その代わりにpatch-report コマンドの利用を 考えたほうが良いでしょう:

        % larch patch-report --diffs patch-1
        [...]

例に沿って読み進めてきたのなら、以前に導入したwhat-changed コマンドからのpatch-report の出力形式を理解できるでしょう。 (ああ、なんてこと — いったい何をしてしまったんだ?項 参照)。

patch-report はまた–– html をとることができ、 その場合チェンジセットを記述する簡単な web ページを生成するのに利用することが できます。

commit をうまく使うこと — きれいなチェンジセットの概念

変更の組をコミットすることが、一般的に言って、"きれいなチェンジセット"を作る ための「最良の練習」になります。

きれいなチェンジセットとは、すべてが関連していて、一つの目的のために 作られた変更のみを含んでいるようなもののことをいます。たとえば、 もしあなたがいくつかのバグを修正したか、いくつかの機能を追加する場合、 そのような変更をひとつのcommitにまとめてしまわない ようにすべきです。

きれいなチェンジセットにはいくつもの利点がありますが、その中でも もっとも大きな点は:

再検討のしやすさ 一つのことだけをやろうと しているチェンジセットを他の人が理解するのはやさしいことです。

マージしやすさ 後の章で学ぶように、 アーカイブ中のチェンジセットの集まりを見て、その中のいくつかを選択 して利用したいような状況があります。多分あなたは、「バグフィックスA 」は利用したいが、「新機能B」は利用したくない、 というケースです。もしチェンジセットのそれぞれが一つの目的を持って いれば、そのような"つまみ食い"は、ずっと現実的なものになります。

第18章 replay の導入 — update の代わりの方法

update は、開発パスについていく唯一の方法ではありません。 他の選択肢としてreplayがあります。

        % cd ~/wd/project-tree
        % larch replay --in-place .
        [....]

それは実際には何をするのでしょうか?

update のリフレッシュ機能

hello-worldの古いバージョンをチェックアウトしたとしましょう:

        % cd ~/wd
        % larch get hello-world--mainline--0.1--patch-1 hw-patch-1
        [...]

結果としてのツリーは最新ではないのは見やすいです:

        % cd hw-patch-1
        % larch whats-missing
        patch-2
        patch-3

ここで何かhw-patch-1にローカル修正を加えてから updateを実行するとします。何がおこるでしょうか?

ローカルな変更は、patch-1 に対して計算されます 言い替えると チェンジセットは、patch-1リビジョンの修正前コピーからプロジェクトツリーの 現在の状態(hw-patch-1)までの変更を表現するようなチェンジセットが作成され ます。

patch-3 のコピーはチェックアウトされます。 update は、patch-3リビジョンの編集前コピー で始まります。

チェンジセットは、patch-3 のツリーに対して適用されます。 最初のステップで計算された変更は、新しいツリーに適用されます。

しかし、別の方法もあります:

リプレイコマンド

この時点でpatch-1のローカルコピーがあり、多分それはローカルな 変更がされているでしょう:

        % cd ~/wd/hw-patch-1
        % larch whats-missing
        patch-2
        patch-3

Recall that the patch-2patch-3 のリビジョンのそれぞれは、 特定のチェンジセットに対応していて、アーカイブ中に格納されていることを思い出してください( どのように動作するか — 新しいリビジョンのコミット項参照)。

ローカルツリーに対してそのような変更を追加するのに get-patch を使って それぞれのチェンジセットを抽出し、dopatchを使って適用することができた のでした(get-patch はアーカイブからチェンジセットを取り出します項dopatch項を参照してください)。 しかし、それにはたくさんの面倒な作業になるので、 archは、同じ効果をもつような自動的な方法を用意しています:

        % cd ~/wd/hw-patch-1
        % larch replay --in-place .
        [....]
        % larch whats-missing
        [no output]

replay ––in-place は、いま説明したことをやってくれます: アーカイブからパッチを取得し、それぞれをひとつひとつ適用していきます。 しかし、ひとつ注意があります:もしそのなかの一つが衝突を起こした場合、 replayはそこで止まり、衝突を直すようにユーザに求めます。 それから、replayが残した部分についてreplay ––in-place を実行することでもう一度選ぶことができます。

どのように動作するか — replay ––in-place

もし、いままでチュートリアルに沿ってやってきたのなら、 replay ––in-place の動作は自明です。 事実、それはまさに上に述べたことだからです。 replaywhats-missing を自分のツリーがやり忘れた変更を発見するのに使い、get-patch をそのような チェンジセットを抽出するのに使い、 dopatchで実際に適用するからです。 それをやるのに十分な量の 「記録」 があります。 — そしてその記録は replay が自動実行してくれることになります。

第19章 選択したファイルのコミット

以前、ツリーにしたすべての変更を一度にコミットする方法について学びました (第12章参照)。

また、「きれいな」チェンジセットを作ることの重要正についても 少し理解していることと思います (commit をうまく使うこと — きれいなチェンジセットの概念項参照)。

この章では通常の状況ではない、非常に特殊な状況で利用できる技法について お見せします。

すぐに修正することについての問題

大きなプロジェクトツリーからあり、ある複雑な修正のまっただ中にいるとします。 あなたはたくさんのファイルを修正しましたが、まだやっていない他の修正が たくさんあるとします。

ここで不意にまだ触れていないファイルのどれかに つまらないバグがあることに気づいたとします。

あなたがやりそうなこととしては:

1) 作業を中断して、そのバグを修正し、

2) その修正をコミットし、

3) 再び複雑な修正作業に戻る、という方法です。

どうやってそれをやることができるでしょう?

ちょっとした問題の修正に対する乱暴な解決方法

この問題を解決するのに、簡単で「乱暴な」方法があります。

単に:

最後のリビジョンのきれいなコピーをチェックアウトします。 言い替えると、変更のまったくない第二のプロジェクトを作ります。

新しいツリーでそのつまらないバグを修正しコミットします。 これで、そのつまらないバグ修正を加えたきれいな変更をコミットします。

update か replay コマンドによって、元のツリーを最新に状態にします。 部分的に完了した変更と共に、自分のツリーに対してささいなバグ修正を追加します。

それは動くには動きますが、面倒です。 ちょっとしたバグを潰すためだけに、二つ目のプロジェクトを始めたいと本当に 思いますか?

しばしば、その面倒さは報われることもあります。 たとえば、プロジェクトは、コミット前には必ずなにかのテストを 実行しなくてはならないというような決まりがある場合です。そのような場合、本当に 二つ目のツリーが必要となるでしょう。

別の状況では、その面倒な処理は本当に避けたいことになります。たとえば もしそのささいなバグ修正が、すでに大きな変更を加えてしまったファイルの修正を ともなうような場合です。そのときでも乱暴な方法は一番単純なアプローチではあります (しかしまた、 larch undo ––helplarch redo ––helpを見てください)。

しかし、ときどき許容される、もっと簡単な方法もあります:

commit ––filesを使った、ちょっとした修正問題の解法

すでにおわかりのように、commit コマンドには ––files オプションがあり、いくつかのファイルにした変更だけをコミットすることができます。

もしちょっとした修正点を file-a.cfile-b.cにたいして やった場合、ログメッセージを用意した後で、そのようなファイルを以下のようにコミットすることが できます:

        % larch commit --files -- file-a.c file-b.c

commit ––files でコミットされるファイルは新しいファイルであっては ならず、そのファイルが名称変更されたとしても、commitはそのようなファイルの 内部的な変更だけを記録し、名称変更したものについては記録しません。

第20章 ブランチの初歩 — プライベートな変更の保守

この章では、おそらくすでに別のリビジョン管理システムで馴染みのある、 "ブランチ"の概念について話しを進めます。

すでにこの概念について馴染んでいる人は、archでのブランチ の考え方は、一般的なものよりもずっと奥が深いことに注意すべきです。

この概念に馴染み深いかどうかにかかわらず、心配は要りません — ゆっくり始めるので:

ブランチのシナリオ — プライベートな変更の必要

しばらくのあいだ hello-world プロジェクトはソースコードが公開 されていて、読み込み専用のミラーになっているとします( 第14章参照)。

まず、あなたは (hello-world プロジェクトに参加していない任意の人は) そのプログラムを利用したいが、自分自身のためのローカルな修正をする必要もあると します。

簡単な場合を考えて、あなたは自分の環境では、"hello world" と表示するのは 受け入れられないとします — きちんとカンマをつけて "hello, world" と 表示することが要求されているとします。

ここで問題がおこります: たしかにソースをダウンロードして変更を加えることは できます。しかし一方でプロジェクトは進行して行きます。彼らはひきつづき 修正を加えるでしょう。こうしてあなたは彼らの最新のソースをダウンロードしては その最新版に対して自分の変更をコピーする、という作業を繰り返ししなくては ならないという問題に直面します。

arch そのような作業の自動化を助けることができます。 この章ではそのやり方について説明します。

ローカルアーカイブにリモートプロジェクトのブランチを作ること

以下の例では、あなたの役割を変えます。hello-worldプロジェクト上の プログラマ、アリスとボブを「演じる」代わりに、第三者である キャンディスを演じます。

キャンディスに彼女自身のアーカイブを与えるところから始めましょう。 そのアーカイブを彼女のデフォルトアーカイブとします:

        % larch make-archive lord@emf.net--2003-candice \
                             ~/{archives}/2003-candice

        % larch my-default-archive lord@emf.net--2003-candice
        default archive set (lord@emf.net--2003-candice)

(このコマンドが何をするかについては、 第6章を復習してください)。

キャンディスは自分のアーカイブ中に hello-world プロジェクトを 作る必要があります。 以下のコマンドを使うことができます:

        % larch make-category hello-world
        % larch make-branch hello-world--candice
        % larch make-version hello-world--candice--0.1

彼女はアリスとボブの使っている同じ名前をプロジェクト名に 選ぶ ことは できません。実際この場合彼女は別のブランチ名前を選びました (これらのコマンドについては 第7章参照のこと)

アリスとボブがアーカイブを作ったとき、最初のリビジョンを作るためにimport を使いました。私達は ブランチを作るので、別のコマンドを使います。

例として、キャンディスはアリスとボブのアーカイブの patch-1 リビジョンから始めるものとします:

    % larch tag \
        lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1 \
        hello-world--candice--0.1
    [....]

このコマンドについていくつか注意しておくべきことがあります。

まず、私達は 完全に修飾されたリビジョン名 を使って アリスとボブの patch-1 リビジョンを参照しました。 それはそのリビジョンは、現在のデフォルトアーカイブ以外のアーカイブ中にある リビジョンであるからです。 (一度に複数のアーカイブを使った作業項参照)

次に私達は patch-1 のリビジョンを明示的に指定しなくてはなりません。 もし ––patch-1 サフィックスを省略すれば、 tag コマンド はアリスとボブのアーカイブの最新のリビジョンを指定したものと考えます (それは patch-3 ということになるでしょう)。

タグの役割

tagを使った後キャンディスは自分のアーカイブ中に新しいリビジョンを 持つことになります:

   % larch revisions --summary hello-world--candice--0.1
   base-0
       tag of lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1

彼女は普通の方法でそのリビジョンを抽出することができます:

   % larch get hello-world--candice--0.1 hw-candice
   [...]

   % ls hw-candice
   hw.c         main.c          {arch}

arch のNiftyな機能: もし注意深く読み進めてきたのなら、キャンディスは他のアーカイブ中に保存された arch のリビジョンから自分のアーカイブ中にブランチを作ったことに気づくでしょう。 今の例だと、これら両方のアーカイブはローカルファイルシステム上に ありますが、それは必要なことではありません: キャンディスはネットワーク越しに アリスとボブのアーカイブにアクセスできる場合でも、ブランチを作ることが できます。

利用についての注意: キャンディスの作業はまだ済んで いません。次の章では、彼女が多分やりたいと思う別のステップについて 説明します。

タグリビジョンのキャッシング

キャンディスは tag を使って、アリスとボブのアーカイブからブランチを 作りました。そのリビジョンをチェックアウトするためにgetコマンドを実行 すると、何がおこるのでしょうか? 大雑把にいって、archはそのリビジョンがブランチであることに気づき、 アリスとボブのアーカイブから実際にソースを取得しようとします。

すると疑問が湧きます: もしアリスとボブがアーカイブを「捨てて」しまったら? いままでの説明を考えるとわかるように、もしそうなった場合、キャンディスは もはや彼女自身のブランチを取得することはできません。

しかし彼女は自分のアーカイブ中にそのリビジョンを構築するのに必要な すべての情報をキャッシュすることで問題を回避することができます:

   % larch archive-cache-revision hello-world--candice--0.1--base-0
   [...]

そして、この処理結果は以下のコマンドで確認できます:

   % larch archive-cached-revisions hello-world--candice--0.1
   hello-world--candice--0.1--base-0

その後 arch は、キャンディスのbase-0リビジョンを 抽出するのに、アリスとボブのアーカイブに依存する必要はなくなります。

新しいブランチの調査

以前にキャンディスは自分のブランチを作って get でチェックアウト しました。そのツリーの中を見てみましょう:

        % cd ~/wd/hw-candice

        % larch logs
        lord@emf.net--2003-candice/hello-world--candice--0.1
        lord@emf.net--2003-example/hello-world--mainline--0.1

キャンディスのツリーはアリスとボブの両方のバージョンのパッチログを 持っています。そして彼女自身のブランチのものも持っています:

    % larch log-ls --summary \
            lord@emf.net--2003-example/hello-world--mainline--0.1
    base-0
        initial import
    patch-1
        Fix bugs in the "hello world" string


    % larch log-ls hello-world--candice--0.1
    base-0
        tag of \
        lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1

キャンディスのブランチ上ではその後の変更はありません:

        % larch whats-missing hello-world--candice--0.1
        [no output]

しかし、アリスとボブは patch-3の用意ができています:

        % larch whats-missing -A lord@emf.net--2003-example \
                hello-world--mainline--0.1
        patch-2
        patch-3

ローカルな変更を加えること

最初の tagの後で, キャンディスは普通の方法で自分のブランチに 変更をコミットすることができます。

彼女は hw.c を編集したとします。すると ( 一部だけ抜粋すると):

        % cat hw.c
        [...]
        void
        hello_world (void)
        {
          (void)printf ("hello, world\n");
        }
        [...]

そして、彼女はログメッセージを用意します:

    % cat ++log.hello-world--candice--0.1--lord@emf.net--2003-candice
    Summary: Punctuated the output correctly
    Keywords: 

このプログラムは "hello word"の代わりに "hello, world" と表示するでしょう。

これで彼女は普通の方法でコミットすることができ、自分自身のpatch-1リビジョン を作ることができます:

   % larch commit
   [....]

   % larch revisions --summary hello-world--candice--0.1
   base-0
       tag of \
       lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1
   patch-1
       Punctuated the output correctly

ブランチからのバージョンを更新すること

一方アリスとボブは自分たちのリビジョン、 patch-2patch-3を作ったとします。 アリスはどうやって彼女のブランチにその変更を追加することができるのでしょうか?

arch はこういうことのためにたくさんの方法を用意しています。 すでに導入されたコマンドを使うとすると、彼女は updatereplay を使うことができます。今回はreplayを使ってみましょう。

        % cd ~/wd/hw-candice

        % larch replay --in-place \
                -A lord@emf.net--2003-example \
                . \
                hello-world--mainline--0.1
        [...]

Note that we used a -A オプションを使って、どのアーカイブ からの変更をリプレイするか、そして、バージョン名で、どの変更が欲しいかを 指定したことに注意してください。今回の場合 replay は、キャンディスのツリーに対して、 patch-2patch-3 のチェンジセットを適用しました。

このreplay の使いかたは、"マージ"の形になっています: キャンディスのローカルな変更はアリスとボブの主系での変更を マージしました。

注意: 例に沿って読んできたのなら、 hw.c を調べてキャンディスの printf 文字列への変更と、アリスの「copywrong」の注意書きの両方が含まれている ことに注意してください。

注意: また、キャンディスのpatch-1リビジョン の二つめのコピーをチェックアウトして、同じマージ処理を、replayの代わりに updateを使ってやってみることもできます。'larch update -help' を使って どのオプションと引数が用意されているかを調べるこができます。

また、以下のことにも注意してください。いままでこのような変更を キャンディスのツリーに対してだけやってきました — キャンディスのアーカイブにはチェックインしませんでした。実際に彼女のアーカイブ にマージを記録するには、ログメッセージを作って、通常のやり方でコミット しなくてはなりません( 第12章参照).

もう一点だけ指摘しておきたいもっと便利な方法があります。 キャンディスが自分のログメッセージを書くとき、マージが行われたことと、 それに含まれていることについて書きたいと思うかも知れません。 arch は、そのようなログメッセージ中に含まれるものと同じ になるような出力をもつコマンドがあります。

  % cd ~/wd/hw-candice

  % larch log-for-merge
  Patches applied:

    * lord@emf.net--2003-example/hello-world--mainline--0.1--patch-3
       added copywrong statements

    * lord@emf.net--2003-example/hello-world--mainline--0.1--patch-2
       commented return from main

どのように動作するのか — タグと基本的なブランチについて

tag がしたことは何でしょうか? キャンディスのアーカイブを 見てみましょう:

        % cd ~/{archives}
        % cd 2003-candice
        % cd hello-world
        % cd hello-world--candice
        % cd hello-world--candice--0.1

        % ls
        +version-lock   =README         base-0          patch-1
        patch-2

あるいは、特に興味を引くのはbase-0 リビジョンです — それは、tagで作られたものです:

        % cd base-0

        % ls
        CONTINUATION
        hello-world--candice--0.1--base-0.patches.tar.gz
        hello-world--candice--0.1--base-0.tar.gz
        log

        % cat CONTINUATION
        lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1

ファイルCONTINUATION はこのリビジョンをタグリビジョンとして 判別します。それはどのリビジョンからブランチを作ったのかを教えてくれます。

このリビジョンのチェンジセットもまた (....patches.tar.gz) tagから作られました。もしチェンジセットを調べれば、(get-patchpatch-reportを思い出してください) それがやったことは、ツリーのパッチログに ログのエントリを追加したことだけだということがわかるでしょう。

ソースファイル (...base-0.tar.gz) は archive-cache-revisionによって作られました。 それはキャンディスのbase-0リビジョンの完全なコピーを含んでいます。 そのファイルはあるので、getはこのリビジョンを構築するためにアリス とボブのアーカイブを見る必要はありません。

第21章 いくつかの利用に関するアドバイス — プライベートなミラーを作ること

以前、どのようにしてネットワーク越しにアクセスできるアーカイブとミラーを 作るかについて学びました (第14章参照)。

その後、リモートアーカイブからローカルブランチを作ることについても学びました。 (第20章参照)。

その後の章で、リモートアーカイブの喪失から自分自身を守るために archive-cache-revision を使う方法について学びました。 第20章参照)。

この章ではarchive-cache-revisionの代案について触れます。 新しいコマンドはなにも導入されません: 単に既に知っているコマンドの新しい 使い方について触れます。

他のことの中で、ここで導入されるテクニックは他の人がネットワーク越しに アクセスすることのできるアーカイブに対する日常的なアクセスを効率化する ことができます。

リモートアーカイブのもついくつかの問題

リモートアーカイブは少なくとも二つの欠点があります:

まず、それは消えてしまうことがあります。 もしネットワークがダウンしたり、リモートアーカイブの管理者がそれを 保持しなければ、アーカイブはなくなってしまいます。

次に、そのようなアクセスは遅い場合があります。 リモートアーカイブは、まさに、リモートな場所にあります。その内容にアクセスすることは、 リモートデータにへのネットワークアクセスの通常の遅延の問題が起こります。

もしリモートアーカイブが重要なデータを含んでいる場合、この欠点は 深刻なものになります。そのようなリスクを減らすにはどうしたら 良いのでしょうか?

ローカルコピーの保持

互換性についての注意: この章で説明する方法は 今後のリリースでは変更になるかも知れません。ミラーはもっとすっきりとサポートする かも知れません。それでもこの方法は作業をうまくやるのに"十分良い"方法です。

少しディスクは食いますが、本質的に以下の二つのステップによって、リモートアーカイブに関する 問題を最小限にすることができます。

リモートアーカイブを第二の名前で登録します。 register-archiveを使うときに、リモートアーカイブをもともとの名前とは 別の名前にします。

ローカルコピーを作るために、push-mirror を使います。 リモートアーカイブのミラーである、ローカルアーカイブを作ります。そのミラーを、アーカイブの 名前で登録します。 push-mirror を使って、リモートアーカイブを自分のプライベートなミラーに コピーするのに使います。(読み込み専用のアーカイブのミラー項参照)。

第22章 パッチログとプロジェクトツリー履歴

前の章で、ブランチとマージについて学び始めました。どのようにしてプロジェクトの複数のブランチを 管理したり変更を適用するために whats-missing, update, そして replay のようなコマンドを使うことができるのかを見てきました。

この章では"パッチログ"について少し説明します: それはプロジェクトツリーの履歴 を管理するのに利用される仕組みです。それは複雑なマージに利用することが できる履歴の一部も含んでいます。

以前の章で最初にパッチログが出て来たことを思い出してください。 (たとえば、プロジェクトツリーを最初に初期化した時です。 第8章参照)。この章では パッチログについてより詳しく説明していきます。

プロジェクトツリーはパッチログを持っています

アーカイブ中の全ての最初のインポート、タグリビジョン、そしてチェンジセットリビジョン はそれに関連したログメッセージを持つことを思い出してください。そのメッセージは importcommitのようなコマンドに明示的に渡す ヘッダとボディー、そしてarchによって自動的に生成されるヘッダからなります。

プロジェクトツリーが最初にアーカイブにインポートされるとき、新しいリビジョンの ためのパッチログエントリがツリーに追加されます。 コミット処理全体の一部として、commitが起こると、新しいリビジョン のログエントリがツリーに追加されます。tagコマンドによって 作成されたリビジョンをgetする場合、そのタグリビジョンのための パッチログエントリを含んでいることがわかるでしょう。

パッチログエントリは蓄積されます。それで例えばそれぞれのコミット は新しいログエントリを追加し、以前のすべてのログエントリは保存されたままです。 それぞれのタグリビジョンはそのタグのためのエントリのみを含むのではなく、 タグづけされたリビジョンから受け付いたすべてのログエントリを含んでいます。

前の例に戻って、アリスとボブのpatch-2リビジョンを見てみましょう:

        % cd ~/wd

        [... remove directories from earlier examples ...]

        % larch get -A lord@emf.net--2003-example \
                    hello-world--mainline--0.1--patch-2 \
                    hw-AnB-2

        [...]

        % cd ~/hw-AnB-2

最初にパッチログは arch のバージョン名でソートされることに注意 してください。このツリーは一つのバージョンのみからのログを持っています:

        % larch logs
        lord@emf.net--2003-example/hello-world--mainline--0.1

そのログ中で、最初のインポートのログと、ふたつのチェンジセットがあります:

        % larch log-ls -A lord@emf.net--2003-example \
                       --summary \
                       hello-world--mainline--0.1
        base-0
            initial import
        patch-1
            Fix bugs in the "hello world" string
        patch-2
            commented return from main

特にこのようなログエントリの一つについて調べてみます:

        % larch cat-log -A lord@emf.net--2003-example \
                        hello-world--mainline--0.1--patch-2
        Revision: hello-world--mainline--0.1--patch-2
        Archive: lord@emf.net--2003-example
        Creator: Tom (testing) Lord <lord@emf.net>
        Date: Wed Jan 29 12:46:50 PST 2003
        Standard-date: 2003-01-29 20:46:50 GMT
        Summary: commented return from main
        Keywords: 
        New-files: \
          {arch}/[...]/hello-world--mainline--0.1/[...]/patch-log/patch-2
        Modified-files: main.c
        New-patches: \
          lord@emf.net--2003-example/hello-world--mainline--0.1--patch-2

        Added a comment explaining how the return from main
        relates to the exit status of the program.

例えば、patch-2チェンジセットはmain.cを修正し、 新しいファイルとログエントリ自身を追加しました。(上の出力中ではその名前は省略して あります)。

別の例はキャンディスのツリーからのものを考えると良いです。 彼女はpatch-1リビジョンでアリスとボブのツリーから分岐する ためにタグを使ったことを思い出してください。それで:

        % cd ~/wd

        % larch get -A lord@emf.net--2003-candice \
                    hello-world--candice--0.1--patch-2 \
                    hw-C-0

        [...]

        % cd ~/hw-C-0

        % larch logs
        lord@emf.net--2003-candice/hello-world--candice--0.1
        lord@emf.net--2003-example/hello-world--mainline--0.1

        % larch log-ls  -A lord@emf.net--2003-example \
                        --summary \
                        hello-world--mainline--0.1
        base-0
            initial import
        patch-1
            Fix bugs in the "hello world" string


        % larch log-ls  -A lord@emf.net--2003-candice \
                        --summary \
                        hello-world--candice--0.1
        base-0
            tag of \
              lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1

どのように動作するか — whats-missing

以前、どのように whats-missing コマンドがアーカイブに対する コミットされた修正について伝えるかについて学びましたが、与えられたプロジェクト ツリーではまだ現れてはいません。 (なぜアリスはコミットすることができないかということについての理解項新しいブランチの調査項を参照のこと)

そのようなコマンドがどのように動作するかを理解するのはやさしいことです。 archは、revisionsコマンドを使って 与えられたバージョン中のすべてのリビジョンの一覧を表示することができます:

        % larch revisions -A lord@emf.net--2003-example \
                          hello-world--mainline--0.1
        base-0
        patch-1
        patch-2
        patch-3

それはアーカイブ中のログです。 arch は、log-lsでログエントリを持つプロジェクト ツリーのためのリビジョンの一覧を表示することができます:

        % larch log-ls -A lord@emf.net--2003-example \
                       hello-world--mainline--0.1
        base-0
        patch-1
        patch-2

二つの一覧の間の違いが whats-missingの出力になります:

        % larch whats-missing -A lord@emf.net--2003-example \
                              hello-world--mainline--0.1
        patch-3

変更履歴とツリーAncestryの概念

パッチログはツリーの履歴に重要な情報を与えます。 注意しておく価値のある二つの見方があります: "変更履歴"の見方と、 "ツリーancestry"の見方です。

変更履歴

ツリーが与えられたコミットのチェンジセットのログを持つ場合、 それはそのコミットからの変更がツリーに対して適用されたことを 意味します: そのコミットのチェンジセットはツリーの『 変更履歴』の一部です。例えばもしチェンジセットがバグ修正であったなら、おそらく それはそのバグ修正がツリー中に存在することを示すものでしょう。

注意: 与えられたチェンジセットがツリーの変更履歴の 一部であるという事実だけでは、そのチェンジセットによって加えられた修正がツリー中に 存在していることの絶対的な証明とはなりません。たとえばそのような変更はそれ以降の 修正によって『取り消された』かも知れません。にもかかわらず、ツリーの 変更履歴はその状態を調べ、理解するのに便利な道具です。

ツリー Ancestry

非公式には、アーカイブされたリビジョンは、もし与えられたツリーがアーカイブされたリビジョンの バージョン中にある全てのリビジョンのログエントリを持っているなら、そのプロジェクトツリーの "ツリーancestor"である、と言います。

それで例えば、キャンディスのタグリビジョンはアリスとボブのpatch-1リビジョンを ancestor として持ちますが、それはアリスとボブのリビジョンを持っているためです:

        base-0
        patch-1

さらにキャンディスの patch-2 リビジョンはアリスとボブの patch-2patch-3の変更をマージした ものですが、このふたつのリビジョンを追加の ancestor として持ちます (ブランチからのバージョンを更新すること項参照。)

自動化されたチェンジログ

larch changelog コマンドは、GNU-スタイルの ChangeLog ファイルを パッチログから生成します:

  % cd ~/wd

  % larch get -A lord@emf.net--2003-candice \
              hello-world--candice--0.1 \
              hw-C-latest
  [....]

  % cd ~/wd/hw-C-latest

  % larch changelog
  # do not edit -- automatically generated by arch changelog
  # tag: automatic-ChangeLog-- [...]
  #

  2003-01-30 GMT  Tom (testing) Lord <lord@emf.net>       patch-2

      Summary:
        merge from mainline sources
      Revision:
        hello-world--candice--0.1--patch-2
  
      Patches applied:
      
        * lord@emf.net--2003-example/hello-world--mainline--0.1--patch-3
           added copywrong statements
      
        * lord@emf.net--2003-example/hello-world--mainline--0.1--patch-2
           commented return from main
      
  
      new files:
       {arch}/ [...] /hello-world--mainline--0.1 [...] /patch-2
       {arch}/ [...] /hello-world--mainline--0.1 [...] /patch-3
  
      modified files:
       hw.c main.c
  
      new patches:
       lord@emf.net--2003-example/hello-world--mainline--0.1--patch-2
       lord@emf.net--2003-example/hello-world--mainline--0.1--patch-3
  
  
  2003-01-30 GMT  Tom (testing) Lord <lord@emf.net>       patch-1
  
      Summary:
        Punctuated the output correctly
      Revision:
        hello-world--candice--0.1--patch-1
  
      
      This program should say "hello, world" not "hello world".
      
  
      modified files:
       hw.c
  
  
  2003-01-30 GMT  Tom (testing) Lord <lord@emf.net>       base-0
  
      Summary:
        tag of lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1
      Revision:
        hello-world--candice--0.1--base-0
  
      (automatically generated log message)
      
  
      new patches:
       lord@emf.net--2003-example/hello-world--mainline--0.1--base-0
       lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1
  

生成されたChangeLogtag の行を含んでいることに 注意してください。プロジェクトツリー中の changelog コマンドの出力を 省略したい場合は、暗黙的なタグを使うか、tagにマッチする明示的なタグを 与えることで、commit のようなコマンドは自動的に ChangeLog を最新の状態に保ちます。

第23章 より進んだブランチ — 星型マージスタイルの共同作業

前の章でhello-world を拡張した例を見てきました。

アリスとボブがプロジェクトの主な開発者であるとして、 ひとつのアーカイブから始めて、そこにいくつかのリビジョンを作ったと しましょう。

そのプロジェクトのユーザであるキャンディスは自分自身をアーカイブを作り、 hello-worldプロジェクトをブランチを始め、 自分自身のローカルな修正を管理し始めたとします。

この章では、実際の世界でのフリーソフト開発のもっと典型的な状況を考えて いきます。ここで、アリスとボブは公開プロジェクトの管理者で、 キャンディスはそのプロジェクトに対する主要なリモート貢献者であると します。そのような状況であらたに必要になるリビジョン管理システムの 機能を特定し、そのような要求を満たすのを助けるようなarch のコマンドのいくつかを見ていきます。

基本的なブランチから、より複雑なブランチへ

いままで、例にそって読み進めてきたのなら、キャンディスは基本的なブランチを 持っているはずです。彼女は主系からブランチを作り、ローカルな修正を加え、 アリスとボブの主系の最新の内容を自分のブランチに反映しました。

この時点で、アリスとボブはキャンディスの変更を主系にマージしたいと 思っているとします。

実際にはそのようなマージ作業はすでに済んでいます。キャンディスの 最後のリビジョンはまさにアリスとボブがほしいと思っているもの だからです。キャンディスの最後のリビジョンを彼ら自身の主系に コミットすることによって、アリスとボブは非常に簡単に そのようなマージすることができます。

        % larch get -A lord@emf.net--2003-candice \
                    hello-world--candice--0.1 \
                    hw-C
        [...]


        % cd hw-C

        % larch set-tree-version -A lord@emf.net--2003-example \
                    hello-world--mainline--0.1

        % larch make-log
        ++log.hello-world--mainline--0.1--lord@emf.net--2003-example

        [... edit log file (consider larch log-for-merge) ... ]

        % cat ++log.hello-world--mainline--0.1--lord@emf.net--2003-example
        Summary: merge from Candice's Branch
        Keywords: 

        Patches applied:

          * lord@emf.net--2003-candice/hello-world--candice--0.1--patch-2
             merge from mainline sources

          * lord@emf.net--2003-candice/hello-world--candice--0.1--patch-1
             Punctuated the output correctly

          * lord@emf.net--2003-candice/hello-world--candice--0.1--base-0
             tag of 
              lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1

        % larch commit
        [....]

注意。よく読んでください: いま使った"トリック"に注意してください。キャンディスの最後のリビジョンはアリスとボブが まさに欲しいと思っているものでした — 彼らはgetset-tree-version と組み合わせて、キャンディスのツリーを彼らの主系に簡単にコミットでるようなものに変えました。

簡単な開発ブランチ

両方のブランチで開発が進んだところを考えてみましょう。 この目的のため、新しいものを導入します: 複数のブランチとそれらの間のマージを図式化する 方法です。

いまの例では、以下のような状況になっています。


      mainline-0.1                    candice-0.1
      ------------                    -----------
        base-0             -----------> base-0 (a tag)
        patch-1  ---------'             patch-1
        patch-2             ----------> patch-2
        patch-3  ----------'  --------'
        patch-4  <-----------'

これは、candice のブランチは主系からのpatch-1のタグである ことを示しています。: そして、キャンディスのブランチのpatch-2主系patch-3までのすべてのマージがあり、最後に、 主系のpatch-4は、キャンディスのブランチの patch-2までのすべての変更をマージした状態になっています。

マージを示す線が一つもないような図のことを、常に、"単純な開発ブランチ" と言います。

単純な開発ブランチの重要性は、どのようにして二つの開発が一つのプロジェクト 上で非同期的に進めることができるかというモデルだからです。 それぞれの開発ライン上で — それはそれぞれのブランチ上でおこりますが — プログラマは「update/commit」スタイルの共同作業を使います。 (第15章参照)。しかし、 片方の変更は、二つのブランチがマージされるまではもう一方に影響を与えることは ありません。

開発ブランチのマージ問題

主系キャンディス のブランチでもっと いろいろな作業が起こったとしましょう。以下のようになりました:


      mainline-0.1                    candice-0.1
      ------------                    -----------
        base-0             -----------> base-0 (a tag)
        patch-1  ---------'             patch-1
        patch-2             ----------> patch-2
        patch-3  ----------'  --------' patch-3
        patch-4  <-----------'          patch-4
        patch-5
        patch-6


        % larch revisions --summary -A lord@emf.net--2003-candice \
                          hello-world--candice--0.1
        base-0
            tag of 
            lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1
        patch-1
            Punctuated the output correctly
        patch-2
            merge from mainline sources
        patch-3
            added a period to output string
        patch-4
            capitalized the output string



        % larch revisions --summary -A lord@emf.net--2003-example \
                          hello-world--mainline--0.1
        base-0
            initial import
        patch-1
            Fix bugs in the "hello world" string
        patch-2
            commented return from main
        patch-3
            added copywrong statements
        patch-4
            merge from Candice's Branch
        patch-5
            fixed the copyrwrong for hw.c
        patch-6
            fixed the copyrwrong for main.c

私達の目標が、主系での新しい作業内容を、キャンディス のブランチにマージすることである、という状況を考えてみます。言い替えると 以下のようにしたいとします:


      mainline-0.1                    candice-0.1
      ------------                    -----------
        base-0             -----------> base-0 (a tag)
        patch-1  ---------'             patch-1
        patch-2             ----------> patch-2
        patch-3  ----------'  --------' patch-3
        patch-4  <-----------'          patch-4
        patch-5               --------> patch-5
        patch-6  ------------'

そのようなマージはどうやったらいいのでしょうか? 最後のマージ前のキャンディスのリビジョンから始めましょう (patch-4):


        % larch get -A lord@emf.net--2003-candice \
                       hello-world--candice--0.1--patch-4 \
                       hw-C-4
        [....]

        % cd hw-C-4

ここで、実際にはうまく動作しないふたつのやり方があります:

replay は、開発ブランチマージ問題を解決しません

replay主系にあるすべての『反映されていない』 変更をキャンディスのツリーにマージしようとします。適用する チェンジセットの一覧は、以下のようにして求めることができます:


        % larch whats-missing --summary \
                              -A lord@emf.net--2003-example \
                              hello-world--mainline--0.1
        patch-4
            merge from Candice's Branch
        patch-5
            fixed the copyrwrong for hw.c
        patch-6
            fixed the copyrwrong for main.c

この一覧中で問題になるのはpatch-4です。それは、 キャンディスのブランチから、patch-2の 段階までの全ての変更を含んでいます。しかしそのような変更はすでにキャンディス のブランチのpatch-4リビジョンに現れています — それで replay を適用すれば、冗長な部分が発生してしまいます(パッチが衝突してしまいます)

進んだユーザに対する注意: replay コマンドは、主系からpatch-4リビジョンを スキップすることを認めるようなオプションがあります。その手のこと は問題を解決しますが、欠点もあります。まずそれはキャンディスのブランチ のwhats-missingの出力に、patch-4が繰り返し現れる ことを意味します。つぎに、patch-4チェンジセットがキャンディス のブランチからのマージだけを含んでいるということを保証できません。 もしアリスとボブがpatch-4に別の変更を加えたのなら、そのチェンジセット をスキップするので、その部分の変更は失われてしまいます。

update は開発ブランチマージ問題を解決しません

主系のブランチからupdateしてみましょう。update は、プロジェクトツリーの一番若い主系の祖先から、ツリー自身までのチェンジセットを 計算し、それを最後の主系リビジョンに適用するものであることを思いだしください。

これを表現する記法を示します。 X から Y へのチェンジセットを以下のように書きます:

        delta(X, Y)

この場合 update主系 patch-3 のリビジョンから、私達のプロジェクトツリーまでのチェンジセットを計算することで 始まります。

        delta(mainline--0.1--patch-3, hw-C-4) 

XからYまでのチェンジセットを、ツリーZに 適用した結果のツリーは、以下のように書きます:

        delta(X, Y) [ Z ]

言い替えると、私達の例でのupdate の結果は、以下のように記述することが できます:

        delta(mainline--0.1--patch-3, hw-C-4) [mainline--0.1--patch-6]

しかし、問題があります。主系patch-3 リビジョン はキャンディスのブランチに前もってマージされていません。それで 以下のチェンジセット

        delta(mainline--0.1--patch-3, hw-C-4)

は、他の変更に混じって、キャンディスのブランチのpatch-1patch-2 の変更を含んでいます。

不幸にもそのチェンジセットを適用したツリー、 mainline––0.1––patch-6は、既にキャンディス ブランチの base-0...patch-2 とマージされてしまっています。

replayの場合と同様、update は、冗長な 変更をすることによってマージ衝突をおこすでしょう。

開発ブランチマージ問題を解くための一つの方法

delta の記法を使って、このマージ問題をはっきりさせましょう。

ひとつの可能性は、主系にたいして一番高い優先順位を 与えて、キャンディスからの変更をマージし、それから プロジェクトツリー中にのみ現れるローカルな変更をマージすることに 一番低い優先順位をつけることです。この解決策は、冗長な変更からの 不要な衝突をすることなしに、以下のように書き下すことができます:


   tmp = delta(X, Y)[Z]
     where X = lord@emf.net--2003-candice/hello-world--candice--0.1--base-0
           Y = lord@emf.net--2003-candice/hello-world--candice--0.1--patch-2
           Z = lord@emf.net--2003-example/hello-world--mainline--0.1--patch-4
   

   answer = delta(L,M)[tmp]

     where L = lord@emf.net--2003-example/hello-world--mainline--0.1--patch-4
           M = /usr/lord/examples/wd/hw-AnB

利用に関する注意: マージにおける「優先順位」の概念は、どのようにして (必要な)衝突を扱うかということを処理しなくてはなりません。 主系に対して高い優先順位を与えることで、 他のふたつのツリーが含む衝突のある変更は、.rejファイルに 現れることを保証します。それは以下のような場合には重要なことになりえます。 たとえば、衝突が解消した主系に相対的な変更を最小化したい 場合です(不完全パッチ処理 — どのようにして衝突が扱われるか項 参照)。

似たように見えるが別の解決策が必要になるのは、主系よりも キャンディスのブランチに高い優先順位を与えたい場合です。


   tmp = delta(X, Y)[Z]
     where X = lord@emf.net--2003-candice/hello-world--candice--0.1--patch-2
           Y = lord@emf.net--2003-example/hello-world--mainline--0.1--patch-6
           Z = lord@emf.net--2003-candice/hello-world--candice--0.1--patch-4
   

   answer = delta(L,M)[tmp]

     where L = lord@emf.net--2003-candice/hello-world--candice--0.1--patch-4
           M = /usr/lord/examples/wd/hw-C-4

私達は実際、「手あたり次第の」方法で解決策を実装することもできます。 二つのブランチのマージ履歴を調べ、どのように解決したかを調べ、 必要なツリーをチェックアウトし、チェンジセットを計算するのにmkpatch を使い、dopatchでそれを適用する、という方法です。 しかしこのあとすぐに見るように、archはこの手のマージのために 組み込みのサポートがあります。

星型マージ — 一般的な開発ブランチマージ問題の解決

開発ブランチマージ問題の一般的にな完全な解決策を説明するのは このチュートリアルの範囲を少し越えています。上で見せた二つの解決策は 二つの場合について示していますが、時にはもう少し違った解決方法が 必要な場合もあります。

知っておくべきことは、単純な開発ブランチがある場合には (簡単な開発ブランチ項参照)、 star-merge コマンドは、不要なマージ衝突を起こすことなく それらの間でどのようにマージすれば良いかを知っているということです。

star-merge (ここで示すように––in-place オプションつきの ばあい)は三つの引数をとります: ふたつの arch バージョンとプロジェクトツリー です(名前は ./で始まる必要があります)。これらの引数の順序は それぞれのソースからの変更の順序を決めます。

たとえば、前の節の二つの解決策は以下のようにしても達成することができます:


        # giving the mainline branch precedence over the candice
        # branch:
        # 

        % larch star-merge --in-place \
                  lord@emf.net--2003-example/hello-world--mainline--0.1 \
                  lord@emf.net--2003-candice/hello-world--candice--0.1 \
                  ./hw-C-4


        # giving the candice branch precedence over the mainline
        # branch:
        # 

        % larch star-merge --in-place \
                  lord@emf.net--2003-candice/hello-world--candice--0.1 \
                  lord@emf.net--2003-example/hello-world--mainline--0.1 \
                  ./hw-C-4

利用に関する注意: 以前に説明したマージの解決策は両方とも二つのチェンジセットの適用を含んでいた ことに注意してください。一般的に、そのようなものの片方、または両方は パッチの衝突を起こすかも知れません。もし最初のマージの後衝突が起こった場合は star-merge は中断し、その衝突を解決するチャンスが与えられます。 star-mergeに対する––finish オプション を使って、二番目のチェンジセットを適用します。 (see larch star-merge ––help参照)。

利用に関する注意: star-mergeを使う前に、get/set-tree-version/commit の トリックを使ってキャンディスから主系への 最初のマージ戻しをしました。 (基本的なブランチから、より複雑なブランチへ項参照)。 一般的に、基本的なブランチから、親ブランチへ戻す形の最初のマージは常にこのような方法で 行われるべきです。 (時々、ユーザから star-merge は そのような「組み込みの」トリックを持つべきだという要求があります。 多分、いつかそのようになるでしょう。)

第24章 シンボリックタグ

プロジェクトがより大きく複雑になるにつれ、あるarchバージョンにある 特定のリビジョンにシンボリックな名前を付けることが便利になることが 多くなります。

たとえば、hello-world プロジェクトがたくさんのリビジョンを 持っているとします:

        mainline
        --------
        base-0
        patch-1
        patch-2
        ....
        patch-23

開発が進むにつれ、ときどきおこる「スナップショット」リリースは、 主系からのものになります。すべてのリビジョンが スナップショットになるわけではありませんが、いくつかはそうなります。

どのリビジョンがスナップショットになるかを示すラベルを用意するのは 便利です:

        mainline
        --------
        base-0
        patch-1         snapshot 0
        patch-2
        ....
        patch-12        snapshot 2
        ....
        patch-23        snapshot 3

前に導入したtag コマンドはこの目的に利用することができます (ローカルアーカイブにリモートプロジェクトのブランチを作ること項参照)。

最初にtagに出会ったとき、基本的なブランチの base-0 リビジョンを作るのに使われただけでした。 それはまたリビジョンがタグであるようなすべての ブランチでも利用することができます。

hello-world––snapshots––0.1という名前のブランチを作っていると しましょう。図で書くと:

        mainline                        snapshots
        --------                        ---------
        base-0                --------> base-0 (tag)
        patch-1 -------------'  ------> patch-1 (tag)
        patch-2                '
        ....                  '
        patch-12 ------------'
        ....
        patch-23

patch-23:のためのsnapshot タグを作るには:

        % larch tag hello-world--mainline--0.1--patch-23 \
                    hello-world--snapshots--0.1

その後では:

        mainline                        snapshots
        --------                        ---------
        base-0                --------> base-0 (tag)
        patch-1 -------------'  ------> patch-1 (tag)
        patch-2                ' -----> patch-2 (tag)
        ....                  ' '
        patch-12 ------------' '
        ....                  '
        patch-23 ------------'

結果として、snapshots ブランチは、履歴つきの「シンボル名」の一種です。 以下のコマンドで、そのシンボルによって名付けられた最新リビジョンを手に入れることが できます:

        % larch get hello-world--snapshots--0.1

そして特定のリビジョンを名付けることによってもっと早いリビジョンも手に入れる ことができます。たとえば:

        % larch get hello-world--snapshots--0.1--patch-1

利用に関する注意: 大雑把に言って、ブランチは commit ベースのものであるか (base-0 以降のすべてのリビジョンは commitによって作られます) タグベースのブランチ(すべてのリビジョンはtag によって作られるか)です。 replay, update, star-merge のようなコマンドは そのルールにしたがっているという前提の上に成立しています。 committag をひとつのブランチ上で混ぜて使った場合の動作は 一般的には保証されません。

第25章 つまみ食い的修正

いままで、ひとつのプロジェクト上で、主な開発ブランチから分離された 基本ブランチ上の変更を管理することと、開発ブランチ上でそれとは非同期的な 作業をする方法について学んできました。 (第20章第23章参照)。

この章では、プロジェクトが複数の「分岐」から構成される場合に 有効な第三のブランチについて簡単に説明します — 複数の、等価な 主ブランチについて、です。

少し抽象的ですが、アリスとボブのメインラインが非常に大きなものになったと します:

        mainline
        --------
        base-0
        patch-1
        ....
        patch-23
        patch-24
        patch-25
        ...
        patch-42

ある時点で、多分mainlineの選択についての議論がおこり、 新しい開発者デリックが、彼自身のブランチを定義し、その上で開発を始めたとします:

        mainline                derick
        --------                ------
        base-0          ------> base-0
        patch-1        '
        ....          '
        patch-23 ----'
        patch-24
        patch-25
        ...
        patch-42

私たちはすでに、デリックはupdatereplay コマンドを 使って、彼の現在の状態にメインラインの内容をマージできることを知っていますが、彼が望んでいない ものについてはどうなのでしょう? デリックはpatch-25patch-42 の変更はほしいのですが、patch-23 以降にmainline上で なされたそれ以外の変更については欲しくないとしたら?

デリックは、replay––exact オプションを使う ことによって、mainline の特定の変更を適用することができます:

        % cd ~/wd

        % larch get hello-world--derick--0.1 derick

        % cd derick

        % larch replay --exact -A lord@emf.net--2003-example \
                 hello-world--mainline--0.1--patch-23

        % larch replay --exact -A lord@emf.net--2003-example \
                 hello-world--mainline--0.1--patch-42

        % larch whats-missing -A lord@emf.net--2003-example \
                 hello-world--mainline--0.1
        patch-24
        patch-25
        ...
        patch-41


        % larch log-ls -A lord@emf.net--2003-example \
                 hello-world--mainline--0.1
        base-0
        patch-1
        ...
        patch-22
        patch-23
        patch-42

このような "つまみ食い" 的な変更は、簡単であったり、現実的であったりする必要は ありません。それは、たとえば、mainline での変更が、 「きれいなチェンジセット」であるかどうかに依存します。 (commit をうまく使うこと — きれいなチェンジセットの概念項参照).

にもかかわらず、プロジェクトによっては、特に、たくさんの「分岐」が できるような特徴を持ったものについては、このテクニックは役にたつことが あります。

理解するうえでの注意: replay コマンドはまた ––list オプションをとる こともでき、それは一度にたくさんのチェンジセットをつまみ食いするときに役立ちます。 もし、replay ––exact をよく利用するのなら、larch replay ––help に表示される––list オプションにも目を通してください。

第26章 複数のツリーのあるプロジェクトと設定管理

archによって独立に管理される個別のプロジェクトの組み合わせである "メタプロジェクト"を定義することができます。これは大きな一つのプロジェクトをもっと 管理が簡単な部分に分割し、それぞれが他の部分とは独立に開発でき、それぞれが一つ以上の メタプロジェクトの一部になることができる、といった状況を認めます。

これは、"設定状況"を書き下すことによってできるようになります。設定状況は メタプロジェクトの内容を定義し、どのようにしてソースツリー中で編成することが できるか、を定義するものです。

たとえば arch 自身はメタプロジェクトです。そのソースツリー は以下のようなものが含まれています:

        dists/
          dists/src/
            dists/src/arch/
            dists/src/file-utils/
            dists/src/ftp-utils/
            dists/src/hackerlab/
            dists/src/shell-utils/

そのようなそれぞれのディレクトリはプロジェクトツリーのルートです (それは、"{arch}"という名前のサブディレクトリを持ちます。).

最上位ディレクトリ dists はまたconfigsという 名前のサブディレクトリを含みます。そのサブディレクトリ中に、メタプロジェクトの設定 ファイルがあります。たとえば:

        dists/
          dists/configs/
            dists/configs/regexps.com/  # Tom's configuration files
              dists/configs/regexps.com/devo.arch
              dists/configs/regexps.com/release-template.arch

ここにはdevo.archの内容があります:

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

     ./src                   lord@regexps.com--2002/package-framework--devo
     ./src/arch              lord@regexps.com--2002/arch--devo
     ./src/file-utils        lord@regexps.com--2002/file-utils--devo
     ./src/ftp-utils         lord@regexps.com--2002/ftp-utils--devo
     ./src/hackerlab         lord@regexps.com--2002/hackerlab--devo
     ./src/shell-utils       lord@regexps.com--2002/shell-utils--devo
     ./src/text-utils        lord@regexps.com--2002/text-utils--devo

ファイル中の (非空白、非ブランクの) 行は以下の形式を持ちます:

        LOCATION             CONTENTS

それは、メタプロジェクトを作るためにCONTENTSによって示される リビジョンを取得し、それをLOCATIONにインストールする ことを意味します。CONTENTS フィールドはブランチで あっても(ブランチの最後のバージョンの最後のリビジョンを 取得することになります)、バージョンであっても(そのバージョンの最後のリビジョンを 取得することになります)、リビジョン名であっても(正確にそのリビジョンを取得 することになります)かまいません。

arch ツリーの全体をチェックアウトするため、最初に devoからdists をチェックアウトし、 次にbuild-configを使います:

        % larch get dists--devo dists
        [....]

        % cd dists

        % larch build-config regexps.com/dists.devo
        [....]

メタプロジェクトツリーを手にいれたあとでは、以下のような便利なコマンドが 使えるようになります:

               update-config : update a multi-project tree
               replay-config : replay a multi-project tree

これらのコマンドは、メタプロジェクトにあるサブツリーに対して再帰的にupdate または replay を実行します。

もう一つの設定管理コマンドがあります:

        % larch record-config GENERAL-CONFIG SPECIFIC-CONFIG

それは設定ファイル GENERAL-CONFIGを読み込みます。 それはプロジェクトツリーを調べて、実際にどのリビジョンがLOCATIONs にインストールされているかを調べます。それから、新しい設定ファイル SPECIFIC-CONFIG に書き込みますが、これは CONTENTS を含み、さらにそのファイルは REVISIONSを正確に指定 します。例えばこれはある配布に移ろうとしている特定のリビジョンの記録のために 便利です。

第27章 アーカイブのキャッシュしたリビジョンによる arch の効率化

この章ではarch アーカイブへのアクセスを早くするための方法をひとつ お教えしましょう。

arch のあるバージョンで、たくさんのリビジョンを含んでいる ような場合を考えましょう:

        mainline
        --------
        base-0
        patch-1
        ....
        patch-23
        patch-24
        patch-25
        ...
        patch-42

ユーザは (ローカルに編集元コピーがない場合) patch-42 リビジョンを get したいと します。get は最初にbase-0リビジョンを 取得・展開し、それから順番に patch-<N> チェンジセット を取得し、ツリーに適用します。

もし適用する必要のあるチェンジセットのリストが長いものである場合、 あるいは、ツリーサイズに比較してそれらのサイズの合計が大きい場合、 get の現在の実装は不要で十分ではありません。

get を高速化するひとつの方法は「アーカイブキャッシュリビジョン」 — 「あらかじめ作成した」あるリビジョンをアーカイブと一緒にコピーして おくことによります。

たとえば以下のコマンド:

        % larch archive-cache-revision -A lord@emf.net--2003-example \
                hello-world--mainline--0.1--patch-40

これは patch-40 リビジョンを構築し、それを tar ファイルの形に パッケージ化し、アーカイブ中のpatch-40の中にその tar ファイルの コピーを保存します。

引続き、patch-42get は、最初にpatch-40 のリビジョンのキャッシュされたコピーを取得し、それからpatch-41patch-42 のチェンジセットを取得・適用します: それで 40 個のチェンジセットは省略できます。

利用に関するノード: この時点で、 どのリビジョンをキャッシュし、どれをそうしないかはあなたの判断にまかされて います。例えば、getが遅すぎると感じた場合はいつでも cron作業からのある特定のリビジョンを自動的にキャッシュ するか、単に手でリビジョンをキャッシュするかを決定するかも知れません。 今後、自動的なリビジョンのキャッシュに関するよりよいサポートを追加する ように考えています。

第28章 リビジョンツリーライブラリを使った arch の高速化

いろいろな目的でたくさんのリビジョンの編集元ツリーを含んでいるライブラリが あるのは便利です — 例えば、特定のバージョンのすべてのリビジョン などです。現実的に考えるとそのようなライブラリは、空間効率を考えた 形で表現されなくてはなりません。

Unix のハードリンクはそのようなライブラリを格納する自然な方法を提供します。 引き続くリビジョンのそれぞれは前のもののコピーです。しかし、変更されていない ファイルはハードリンクによって共有されます。

arch はライブラリを構築し、管理し、閲覧するのを助けるコマンドを 用意しています。

好都合なことに arch の多くのコマンドは、処理に必要とするリビジョンが あなたのリビジョンライブラリ中にある場合、高速で動作します。次の章でこれについてもっと 深く理解することができます。

リビジョンライブラリの場所

新しいリビジョンライブラリを始めるのに、まず新しいディレクトリを作り(DIR) それからその場所を登録します:

        % larch my-revision-library DIR

ライブラリの位置は以下のようにして確認できます:

        % larch my-revision-library

登録を解除するには:

        % larch my-revision-library -d

リビジョンライブラリの形式

リビジョンライブラリは以下のような形のサブディレクトリを持っています:

ARCHIVE-NAME/CATEGORY/BRANCH/VERSION/REVISION/

それぞれの REVISION ディレクトリは特定のリビジョンの 完全なソースを含んでいます。さらに補助的なサブディレクトリとファイルも 含んでいます。

REVISION/,,patch-set/

その祖先からこのリビジョンを作ったパッチセット (リビジョンが完全なソースを持ったベースリビジョンではないかぎり)。

リビジョンライブラリ中のファイル上のパーミッションはパッチセットによって 決定されますが、リビジョンライブラリ中のファイルを変更 することはできません。そのようなことをしようとすると、 奇妙なエラーがおこり、いろいろなarchのコマンドで 失敗するようになります。

ライブラリへのリビジョンの追加

ある特定したリビジョンをあなたのリビジョンライブラリに追加する ことができます。以下のようにします:

        % larch library-add REVISION

それは REVISIONをライブラリに追加するだけではなく、 同じアーカイブ、または同じライブラリにある別のアーカイブからの 直接の引き続くリビジョンも(再帰的に)追加します。 (この場合の「直接の引き続く」は、普通のリビジョンまたはタグづけされたリビジョン のための前のパッチレベルを意味します。)

ライブラリ中のリビジョンの検索

library-findコマンドでライブラリ中の特定のリビジョンを検索 できます:

        % larch library-find REVISION
        PATH-TO-REVSION

出力はそのリビジョンを含むライブラリディレクトリの絶対パス名称です。 (繰り返しになりますが、そのディレクトリのファイルを編集してはなりません。)

ライブラリからのリビジョンの削除

ライブラリからの特定のリビジョンを削除するには:

        % larch library-remove REVISION

現在のリリースでは以下の制約があります: 三つの引き続くリビジョンを追加しようとしているとします、A, B, そして Cです。 それからBを削除し再び Bを追加します。 その場合、BCの間のファイルの共有は あまり最適化されないかも知れず、不要に大きな領域を必要とするかも知れません (これは、Cを削除し、もう一度追加すれば解決できます)

ライブラリの内容の一覧表示

コマンド library-archives は、ライブラリ中の全てのアーカイブをその記録と一緒に 一覧表示します:

        % larch library-archive
        ARCHIVE-NAME
        ARCHIVE-NAME
        ...

同様に、カテゴリ、ブランチ、バージョン、リビジョンも表示できます:

        % larch library-categories [ARCHIVE]
        % larch library-branches [ARCHIVE/CATEGORY]
        % larch library-versions [ARCHIVE/BRANCH]
        % larch library-revisions [ARCHIVE/VERSION]

リビジョンライブラリ中の個々のファイル

リビジョンライブラリ中の個々のファイルの場所を以下のようにして知ることが できます:

        % archive library-file FILE [REVISION]
        PATH

あるいはその内容は:

        % archive cat-library-file FILE [REVISION]
        ...file contents...

両方のコマンドはオプション ––tag––thisをとる ことができます。––tagを使うと引数 FILE は 目録タグと解釈され、そのタグが見つけたファイルを指します。

––thisを使うと FILE は現在のディレクトリに相対的な ファイルとして解釈されます。このディレクトリはプロジェクトツリーの一部であるべきです。 ファイルの目録タグは計算され、REVISION中に見付かった対応するファイル になります。

あらかじめ必要なパッチセットの決定

          % larch touched-files-prereqs REVISION

このコマンドは REVISION のためのパッチセットを見て、 同じバージョンのすべての以前のパッチセットを見ます(それはこの目的のために リポジトリではなくライブラリを検索します)。それは、ファイルとディレクトリ の重なったものに関係するようなパッチの一覧を報告します — 言い替えると、それは他と独立に適用できるパッチについての情報を与えます。 このコマンドには特定のパターン(e.g. "=README" や "ChangeLog") にマッチするファイル名称 を排除するようなオプションがあります。 また、既に与えられたプロジェクトツリーに適用されているパッチのリストを除外する ようなオプションもあります。また、重なりあっている特定のファイルについての 報告を要求するオプションがあります。

第29章 arch の通知機能を使った処理の自動化

進行中の開発機能に関する注意: この章で記述されている機能はおそらくarchの1.0のリリース 以前とは互換性のない変更を含んでいます。

ある場面で、アーカイブに対する変更の検出によってある動作がトリガーされる と便利です。たとえば、新しいリビジョンがチェックインされる時は常に emailを送信したいと思うかも知れません。

コマンドnotify はこの機能を提供します:

        % larch notify NOTIFICATION-DIR

このコマンドは NOTIFICATION-DIRにある設定ファイルを読み込みます。 この設定ファイルはどのリポジトリのどの部分を監視するか、また変更によってどのような 動作をするか、についての記述があります。変更が検出されると、notify はその動作を実行します。

この章では notify を一般的に説明します。 NOTIFICATION-DIR の形式と設定ファイルの形式についての説明を します。そしてnotify が何をするかについて説明します。

四つの通知設定ファイル

notify は四つの設定ファイルによって制御されます。 設定ファイルはNOTIFICATION-DIRにあります。それは以下の ものです:

        =rules.archives
                Specifies actions to take whenever new categories
                are added to specific archives.

        =rules.categories
                Specifies actions to take whenever new branches
                are added to specific categories.

        =rules.branches
                Specifies actions to take whenever new versions
                are added to specific branches.

        =rules.versions
                Specifies actions to take whenever new revisions
                are added to specific versions.

これらのファイルの中では空白行があってもよく、コメントは '#'で始まり、行末まで 続きます。

ファイル =rules.versions は、以下のような形式の行を含んでいます:

VERSION ACTION

ここで VERSION は完全に修飾されたバージョン名で、動作は以下の形式 の文字列です(空白があってはなりません):

COMMAND:THUNK

新たらしいリビジョンが VERSION中に検出された場合は常に notify が実行されます:

larch COMMAND THUNK RVN ...

ここで COMMANDTHUNK は設定ファイルからのもので、 最後の RVN 引数は新しく検出されたリビジョンの完全に修飾された リビジョン名のリストです。

ファイル =rules.branches も同様です。それは以下の形式の行を含んでいます:

BRANCH COMMAND:THUNK VERSION-ACTION

新しいバージョンが BRANCHに作られると常に notify は 二つの動作をとります。まず以下を起動します:

larch COMMAND THUNK VSN ...

次に、以下のような形式の新しいルール =rules.versions を追加します:

VSN VERSION-ACTION

=rules.categories=rules.archives はよく似ています。 前者は以下の形式の行を含んでいます:

CATEGORY COMMAND:THUNK BRANCH-ACTION VERSION-ACTION

後者は以下のような形式の行を含みます:

ARCHIVE COMMAND:THUNK CATEGORY-ACT BRANCH-ACT VERSION-ACT

設定ファイルに加えて、notify はプライペートな状態を NOTIFY-DIRに管理します。解くに、それはどのような通知が既に 送信されたかを記録し、同じ通知を何度も送信するのを防ぎます。

リポジトリ中のすべてに対する通知

あるアーカイブ中のすべてのカテゴリ、ブランチ、バージョンにたいして通知を設定するのは とても簡単です: 単に =rules.archivesファイルを書くだけです — 他の設定ファイルはそれから自動的に生成されます。

最初の=rules.archivesファイルは以下のような行を含んでいるべきです:

ARCHIVE COMMAND:THUNK CATEGORY-ACT BRANCH-ACT VERSION-ACT

トリガーしたい動作ごとに記述します。 設定ファイルを作成後、そのディレクトリで notify を実行してください。最初の実行で リポジトリ中のすべてのカテゴリを検出し、それにたいして COMMAND を実行し、以下のような行を持つ rules.categories ファイルを作ります:

CATEGORY CATEGORY-ACT BRANCH-ACT VERSION-ACT

それからnotifyその設定ファイルを読んで、リポジトリ中のすべてのブランチを 検出し、CATEGORY-ACTを実行して =rules.branchesを作ります。

最後に =rules.versions が同様にして自動生成されます。

新しいカテゴリ、ブランチ、バージョンがアーカイブに追加されるたびに 定義ファイルはその追加を反映する形で自動的に更新されます(当り前 ですがnotify が実行されたときにです。)

通知メール

以下のコマンドはアーカイブに新しい追加があったことを知らせる email 送信のためのnotifier のルール中で使うことができます:

mail-new-categories mail-new-branches mail-new-versions mail-new-revisions

以下のコマンドは、新しいリビジョンのために起動された場合、my-revision-library で登録されるリビジョンライブラリにそれらのリビジョンを追加するために使うことが できます:

notify-library

最後に noop コマンドは何の動作も必要ない場合の通知イベントの 置き場所として使うことができます。

これらのコマンドを組み合わせて、=rules.archivesファイルを作り 通知を送り、アーカイブのリビジョンライブラリをアップデートするこが できます(長い行は複数行にしてあります):

        lord@emf.net--2003              mail-new-categories:lord \
                                        mail-new-branches:lord \
                                        mail-new-versions:lord \
                                        mail-new-revisions:lord

        lord@emf.net--2003              noop:notify-library:lord \
                                        noop:notify-library:lord \
                                        noop:notify-library:lord \
                                        notify-library:lord

通知に関する堅牢さの問題

不幸にもこの世界が持っているいくつかの基本的な性質のために、 make it impossible for notify が、それぞれの新しいカテゴリ、 ブランチ、バージョン、あるいはリビジョンに対して、一度だけ起動されることを 経章できない場合があります。 (非常にまれな場合ですが) あるタイミングの割り込みや、システムの異常はnotify に、アーカイブに対する変更に対して、一度異常の動作を起こしてしまうことがあります。

結果として、動作はそのような場兄に対して堅牢な設計となっていなくてはなりません。

notify は並行した起動に対して安全になるよう設計されています: もし二つのプロセスが同時にnotifyを起動した場合、すべてのことが 問題なく動作し、冗長な動作や、 NOTIFY-DIR領域の破壊といった ことはおこりません。

cron によるスケジュール通知

notify を使う戦略のひとつは、cron からの起動です。

archコマンドからの通知のスケジュール

以下のコマンドは (そして以下のコマンドだけが) notifyに対して重要であるような形でarchのリポジトリを 修正します:

        make-category
        make-branch
        make-version
        import
        commit
        tag

もしmy-notifierコマンドで通知ディレクトリを登録した場合:

        % larch my-notifier NOTIFIER-DIR

上にリストしたコマンドは動作完了後、端末から切り離されたデーモンを起動し、 そのディレクトリ中で、larch notifyを起動します。 それらのデーモンの開始時刻、終了ステータスは ~/.arch-params/log-file に記録され、デバッグ上の問題が ある場合には役に立ちます。ときどきのそのファイルをクリアすると良いでしょう。

付録 A. arch のチェンジセット形式

arch のチェンジセットはたくさんのファイルやサブディレクトリの あるディレクトリです。それぞれについて以下で説明していきます。

ファイル:

        orig-dirs-index
        mod-dirs-index
        orig-files-index
        mod-files-index

形式:
        <file path><tab><tag>
ソート:
        sort -k 2

これらは、二つのツリー間でおきた、追加、削除、修正がおきたすべてのファイル とディレクトリのインデックスが入っています。

ファイル:
        original-only-dir-metadata
        modified-only-dir-metadata
形式:
        <metadata><tab><name>
ソート:
        sort -t '<tab>' -k 2

フィールド<metadata>は、オプション–– permissionsで 与えたプログラム file-metadata からの出力が入っています。出力例としては:

        --permissions 777

この出力はまた、オプションとしての利用や、プログラムset-file-metadata へのオプション引数としても適切なものになっています。今後のリリースで、 arch は追加フラグをサポートするかも知れません。 (単なる permissionsに加えて)。

そのリストは、二つのツリーのどちらか一方に現れるすべてのディレクトリの ファイルパーミッションを記録します。

Directories: removed-files-archive new-files-archive

これらのディレクトリはそれぞれ、元のツリー(removed-files-archive) または、修正されたツリー(new-files-archive)のみに現れるすべての ファイルの完全なコピーを含んでいます。それぞれの保存されたファイルはそのソースツリー 中の同じ相対的な場所にアーカイブされ、パーミッションは(少なくとも)保存されます。

Directory: patches

このディレクトリは、そのディレクトリ構造が、修正されたツリーの ディレクトリ構造のサブセットであるようなツリーを含んでいます。 それは、両方のツリーに共通のディレクトリとファイルに修正したデータ を含んでいます。

パスnew_nameにある修正されたツリーに保存されたファイル について、patches ディレクトリは以下のようなものを 含んでいます:

new_name.link-orig

元のファイルはシンボリックリンクです。 new_name.link-origは、そのリンク先と、改行を 含んだテキストファイルです。

このファイルはリンク先が変更された場合のみ存在します。または リンクが通常のファイルによって置き換えられた場合のみ存在します。

new_name.link-mod

修正されたファイルはシンボリックリンクでこのファイルはリンク先と改行 を含んだテキストです。

このファイルはリンク先が変更された場合のみ存在するか、または 通常のファイルをリンクが置き換えた場合のみ存在します。

new_name.original

これは元のツリーからのファイルの完全なコピーです。(少なくても) パーミッションも保存されています。

このファイルはファイルがシンボリックリンクで置き換えられたか、 ファイルの内容がdiff(1)で扱うことが できない場合にのみ存在します。

new_name.modified

これは、修正されたツリーのファイルの完全なコピーです。 (少なくても)パーミッションも保存されます。

このファイルは、ファイルがシンボリックリンクを置き換えたか、 ファイルの内容がdiff(1)で扱えない 場合にのみ存在します。

new_name.patch

これは元のファイルと修正されたファイルとの間の標準的なコンテキスト diff です。 diff のある有名なバージョン(GNU diff) では、 元と修正先のファイル間で同じであるコンテキスト行のコピーを省略する ような、非標準的なコンテキスト diff を生成するので、(XXX) .patch ファイルも同じバグを含んでいます。 幸運にも、patchの唯一のよく知られたバージョン (``GNU patch'') は、そのような入力を我慢して受け取ることが できます。

new_name.meta-orig, new_name.meta-mod

ファイルのメタデータ(現在のところ、パーミッション情報のみ)はファイルの二つの バージョン間で変更されました。これらのファイルは–– symlink –– permissions フラグつきのfile-metadata プログラムからの出力を含んでいて、 同様の出力との比較、オプションとしての利用、set-file-metadata に対するオプション引数、として適した形です。

これらのファイルも通常のファイルがシンボリックリンクを置き換えたり、 逆のことがおきた場合に含まれます。

new_name/=dir-meta-orig, new_name/=dir-meta-mod

ディレクトリのメタデータ(現在のところパーミッション情報のみ)が、それらの ファイルを含むディレクトリの二つのバージョン間で変更されました。これらの ファイルは–– symlink –– permissionsフラグつきの file-metadata プログラムからの出力を含んでいて、 同様の出力との比較、オプションとしての利用、そしてset-file-metadata へのオプション引数、として適した形をしています。

注意: もし普通のファイル(またはシンボリックリンク)が ディレクトリを置き換えるか、その逆の場合、これは一方のツリーでファイル(またはリンク) が削除(または追加)され、もう一方で、追加(または削除)されたものとして記録されます。

付録 B. 目録の名前規約のカスタマイズ

第9章で、larch inventory コマンドが名前規約を使ってプロジェクトツリー中のファイルをどのように分類 するかについて学びました。この補遺はこれらの名前規約をどのようにして カスタマイズすることができるかの説明です。

名前規約をカスタマイズするとき

プロジェクトの名前規約をカスタマイズするのは、最初のリビジョンを importする前がベストです。

もし、あとで変更する必要がある場合は、 その変更をしようとした時点でプロジェクトに存在している 最新のリビジョンの中にすでに存在しているファイルの分類を 変更することができないという事実が重要 です。 (あるいは、奇妙で望まない振る舞いを経験することになるでしょう)

名前規約のカスタマイズの方法

まずは、arch の名前規約項の名前規約のアルゴリズム を復習することから始めてください。それぞれのカテゴリテストに利用される 正規表現を変更することによつてそのアルゴリズムを変更することができます。

プロジェクトツリーの./{arch}/=tagging-methodというファイル を修正することによって名前規約をカスタマイズできます。このファイルは tagging-methodコマンドによって作成され、初期状態では タグづけの方法の名前を示す一行のみが含まれています (names, explicit, あるいはimplicit).

特に =tagging-method はブランク行、コメント ("#"で始まる行)、ディレクティブ行を一行にひとつ含むことができます。 可能なディレクティブ行としては:

        implicit
        explicit
        names
                specify the tagging method to use for this tree

        exclude RE
        junk RE
        backup RE
        precious RE
        unrecognized RE
        source RE
                specify a regular expression to use for the indicated
                category of files.

正規表現はPosix の ERE 構文で指定します(これは、"egrep", "grep -E", そして "awk" で指定されるものと同じ構文です)そして、デフォルトで実装されている 値は、arch の名前規約項で記述されています。

付録 C. The GNU Free Documentation License

GNU Free Documentation License Version 1.1, March 2000

Copyright (C) 2000 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 written 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 that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you".

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. (For example, 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.

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 "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, whose contents can be viewed and edited directly and 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 has been designed to thwart or discourage subsequent modification by readers is not Transparent. 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 designed for human modification. Opaque formats include PostScript, PDF, 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 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.

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 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 publicly-accessible computer-network location containing a complete Transparent copy of the Document, free of added material, which the general network-using public has access to download anonymously at no charge using public-standard network protocols. 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 less than five).

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", and 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.

In any section entitled "Acknowledgements" or "Dedications", preserve the section's title, 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 as "Endorsements" or to conflict in title with any Invariant Section.

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.

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, does not as a whole count as a Modified Version of the Document, provided no compilation copyright is claimed for the compilation. Such a compilation is called an "aggregate", and this License does not apply to the other self-contained works thus compiled with the Document, on account of their being thus compiled, if they 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 quarter of the entire aggregate, the Document's Cover Texts may be placed on covers that surround only the Document within the aggregate. Otherwise they must appear on covers around 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 provided that you also include the original English version of this License. In case of a disagreement between the translation and the original English version of this License, the original English version will prevail.

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.1 or any later version published by the Free Software
      Foundation; with the Invariant Sections being LIST THEIR TITLES,
      with the Front-Cover Texts being LIST, and with the Back-Cover
      Texts being LIST.  A copy of the license is included in the
      section entitled "GNU Free Documentation License".

If you have no Invariant Sections, write "with no Invariant Sections" instead of saying which ones are invariant. If you have no Front-Cover Texts, write "no Front-Cover Texts" instead of "Front-Cover Texts being LIST"; likewise for Back-Cover Texts.

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.

付録 D. The GNU General Public License

arch is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License (GPL) as published by the Free Software Foundation (and reproduced below).

This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License (reproduced below) for more details.

I have chosen to use the GPL for this software because I believe it best reflects the duties to society of a software engineer. It is the best license for users, for my fellow engineers, and for society as a whole. As is beginning to be widely appreciated, this license is a startling profound and influential document and is worthy of study in its own right.

In a commercial climate that grew up mostly under proprietary licenses (those that fall far short of protecting the freedoms and promoting the obligations of the GPL), my choice of this license has, at the moment, made it difficult for me to recover the costs of developing arch and to make a profit from my work going forward. Those are very serious problems, in my opinion. Please see also xref:"Uh....a Little Help Here?".

insert*/

GNU GENERAL PUBLIC LICENSE Version 2, June 1991

Copyright (C) 1989, 1991 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.

Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification follow.

GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.

1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.

You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.

2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:

a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.

b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.

c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.

In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.

3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:

a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.

If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.

4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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.

5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.

6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.

7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.

This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.

8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.

9. The Free Software Foundation may publish revised and/or new versions of the General Public 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.

Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.

10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

NO WARRANTY

11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS

How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.

<one line to give the program's name and a brief idea of what it does.> Copyright (C) <year> <name of author>

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this when it starts in an interactive mode:

Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type show w. This is free software, and you are welcome to redistribute it under certain conditions; type show c for details.

The hypothetical commands show w and show c should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than show w and show c; they could even be mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright interest in the program Gnomovision (which makes passes at compilers) written by James Hacker.

<signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice

This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.

付録 E. ここでちょっと・・・助けてもらえないでしょうか?"

わたくし Tom Lord は、archの作者ですが、非常に長い間失業して おり、唯一の収入は 0 ではないにしても、非常に貧しい状況に置かれています。

(泣) 分かっています。生きるというのは大変なことです。

他の方法がないので、私は自分のすべての退職金を現金化し、持っていたわずかばかりの 株を売り払い、たくさんの持ちものを売り(実際に、ギターとCDを失いました)、そして クレジットカードの負債をかなり増やして、arch の開発を続けています。(カードのいくつかはすぐに不良債権として利用不能になるでしょう)。 どうして私はこんなバカなことをしているのでしょう? ある程度は必要に迫られて — しかし、私はarchは素晴らしいデザインであり、あなたもきっとそう 思ってくれるのではないか、というのも理由のひとつです。

それで、いくつかのお願いがあります:

1) 私は「寄付」をいただける方には感謝します。(ビジネス上の 収入として扱います)私の PayPal アカウント lord@emf.net に送ってください。

2) S.F. のベイエリアでできる仕事に非常に興味があります(特に、 Alameda, S.F. または自宅でできるような) 私は非常に優れた C/Scheme/sh/awk/unix のプログラマです。いや、私は linux の デバイスドライバ、SQL, PHP, TCP/IP スタック, Java Beans, J2EE, Visual Studio などをハックした経験は確かにありませんが。 フリーソフトに関係した仕事の機会については喜んで受け入れたいと 思います。

3) 「実践的な調査」は最も得意とするところです。 私はたくさんのプロジェクトを持っていて、もちろん — archも そのひとつです。それらに投資する良いアイディアがあるようなら、emailをください。

4) arch は (あと 少し の開発で) 商用のリビジョン管理システムに払う多額のライセンスフィーを節約することが できます。IBM, Red Hat, HP/C, United Linux members, Apple, 資本のある潜在的な ビジネスパートナーなどと私は話しをする用意があります。emailをください。

5) 一般論として: 私はお金が必要です (なんでもします) — ですから、何か助けていただく方法があるのであれば、どうか連絡をお願いします。

第30章 Indexes :unnumbered :index (general) :index-for "arch"