[インデックス 17835] ファイルの概要
このコミットは、Goプロジェクトのコードレビューシステムに関連するPythonスクリプトである lib/codereview/codereview.py
の変更です。具体的には、Plan 9オペレーティングシステム上でのファイル作成パーミッションの問題を修正しています。
コミット
commit 6d86d064e5b060ef7ab665ec5d6e3772090a7694
Author: Jeff Sickel <jas@corpus-callosum.com>
Date: Wed Oct 23 10:28:28 2013 -0400
plan9: correct create permissions with union directory
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/15360045
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/6d86d064e5b060ef7ab665ec5d6e3772090a7694
元コミット内容
plan9: correct create permissions with union directory
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/15360045
変更の背景
このコミットは、Plan 9オペレーティングシステム上でGoのコードレビューツールを使用する際に発生していた、ユニオンディレクトリ(union directory)におけるファイル作成パーミッションの問題を解決するために行われました。
Plan 9では、複数のディレクトリを単一の論理的なディレクトリとして結合する「ユニオンディレクトリ」という強力な機能があります。これは、異なるソースからのファイルを透過的にアクセスできるようにするために使用されます。codereview.py
スクリプトは、ユーザーのホームディレクトリ (~
) とその中の ~/lib
ディレクトリをユニオンディレクトリとしてバインドしていました。
しかし、このバインド設定だけでは、ユニオンされたディレクトリ内で新しいファイルを正しく作成するためのパーミッションが不足している場合がありました。具体的には、plan9.bind
関数に plan9.MBEFORE
フラグのみを指定した場合、既存のファイルへのアクセスは可能でも、新しいファイルの作成が意図した通りに行われない、あるいはパーミッションエラーが発生する可能性がありました。この問題は、コードレビュープロセスにおいて、一時ファイルや設定ファイルなどの作成が必要な場合に支障をきたしていました。
このコミットは、plan9.bind
呼び出しに plan9.MCREATE
フラグを追加することで、このファイル作成パーミッションの問題を修正し、Plan 9環境での codereview.py
の正常な動作を保証することを目的としています。
前提知識の解説
Plan 9 from Bell Labs
Plan 9 from Bell Labsは、ベル研究所で開発された分散オペレーティングシステムです。その設計哲学は「すべてをファイルとして扱う」というもので、プロセス、ネットワーク接続、デバイスなど、システム内のあらゆるリソースがファイルシステムを通じてアクセスされます。これにより、シンプルで一貫性のあるインターフェースが提供され、分散システムを容易に構築できます。
ユニオンディレクトリ (Union Directory) / 名前空間の結合
Plan 9の最も特徴的な機能の一つが「名前空間の結合(namespace merging)」、一般に「ユニオンディレクトリ」と呼ばれるものです。これは、複数のディレクトリの内容を単一の論理的なディレクトリツリーに結合する機能です。例えば、/usr/local/bin
と /usr/bin
を /bin
に結合することで、ユーザーは両方のディレクトリにある実行ファイルを /bin
から透過的にアクセスできます。
ユニオンディレクトリは、bind
システムコールによって実現されます。bind
は、あるディレクトリを別のディレクトリに「マウント」するような操作ですが、既存のディレクトリの内容を置き換えるのではなく、結合します。結合の順序(どちらのディレクトリが優先されるか)や、ファイル作成時の挙動などを制御するためのフラグが提供されます。
plan9.bind
関数
plan9.bind
は、Plan 9のファイルシステム操作をPythonから行うためのインターフェースを提供する関数です。これは、Plan 9の bind
システムコールをラップしたものです。
bind(new, old, flags)
の形式で呼び出され、new
ディレクトリを old
ディレクトリにバインドします。flags
はバインドの挙動を制御するビットマスクです。
MBEFORE
フラグ
plan9.MBEFORE
は bind
システムコールで使用されるフラグの一つです。このフラグが指定されると、new
ディレクトリの内容が old
ディレクトリの既存の内容の「前に」結合されます。つまり、同じ名前のファイルやディレクトリが存在する場合、new
ディレクトリ内のものが優先されます。これは、既存のパスを上書きすることなく、新しいパスを追加する際に便利です。
MCREATE
フラグ
plan9.MCREATE
も bind
システムコールで使用されるフラグの一つです。このフラグは、ユニオンディレクトリ内で新しいファイルを作成する際の挙動を制御します。MCREATE
が設定されている場合、新しいファイルはユニオンされたディレクトリの「最も上位のレイヤー」に作成されます。つまり、MBEFORE
で結合されたディレクトリがある場合、そのディレクトリ内に新しいファイルが作成されます。このフラグがない場合、ファイル作成が許可されないか、意図しない場所に作成される可能性があります。
codereview.py
スクリプト
codereview.py
は、Goプロジェクトの初期のコードレビューシステム(おそらくGerritのようなツールと連携していたか、あるいは独自のシステムの一部)とやり取りするためのPythonスクリプトです。開発者が変更をアップロードしたり、レビューコメントを取得したりするために使用されていました。このスクリプトは、Plan 9を含む様々なプラットフォームで動作するように設計されており、プラットフォーム固有のファイルシステム操作を行う必要がありました。
技術的詳細
このコミットの技術的な核心は、Plan 9のユニオンディレクトリにおけるファイル作成のセマンティクスを正しく理解し、適用することにあります。
元のコードでは、以下の行がありました。
n = plan9.bind(os.path.expanduser("~/lib"), os.path.expanduser("~"), plan9.MBEFORE)
この行は、ユーザーのホームディレクトリ (~
) に ~/lib
ディレクトリをバインドし、~/lib
の内容が ~
の既存の内容よりも優先されるように設定していました。これは、~/lib
にあるツールや設定ファイルを ~
から直接アクセスできるようにするための一般的なパターンです。
しかし、plan9.MBEFORE
フラグだけでは、ユニオンされた ~
ディレクトリ内で新しいファイルを「作成」する際のパーミッションが適切に処理されませんでした。Plan 9の bind
システムコールは、デフォルトでは結合されたディレクトリでのファイル作成を許可しないか、あるいは作成されたファイルの場所が意図しないものになる可能性があります。
この問題を解決するために、コミットでは plan9.MCREATE
フラグが追加されました。
n = plan9.bind(os.path.expanduser("~/lib"), os.path.expanduser("~"), plan9.MBEFORE|plan9.MCREATE)
ここで使用されている |
はビットごとのOR演算子です。これにより、plan9.MBEFORE
と plan9.MCREATE
の両方のフラグが bind
システムコールに渡されます。
plan9.MBEFORE
:~/lib
の内容が~
の既存の内容より優先されることを保証します。plan9.MCREATE
: ユニオンされたディレクトリ (~
) 内で新しいファイルが作成されることを明示的に許可し、そのファイルがMBEFORE
によって優先される~/lib
のレイヤーに作成されるようにします。
この変更により、codereview.py
がPlan 9環境で実行される際に、一時ファイルやその他の必要なファイルをユニオンディレクトリ内で正しく作成できるようになり、スクリプトの機能が完全に動作するようになりました。これは、Plan 9のファイルシステムが持つ独特のセマンティクスを理解し、それに対応した適切なシステムコールフラグを使用することの重要性を示しています。
コアとなるコードの変更箇所
--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -65,7 +65,7 @@ from mercurial import util as hg_util
if os.sys.platform == 'plan9':
try:
import plan9
- n = plan9.bind(os.path.expanduser("~/lib"), os.path.expanduser("~"), plan9.MBEFORE)
+ n = plan9.bind(os.path.expanduser("~/lib"), os.path.expanduser("~"), plan9.MBEFORE|plan9.MCREATE)
except ImportError:
pass
コアとなるコードの解説
変更は lib/codereview/codereview.py
ファイルの以下の1行です。
- n = plan9.bind(os.path.expanduser("~/lib"), os.path.expanduser("~"), plan9.MBEFORE)
+ n = plan9.bind(os.path.expanduser("~/lib"), os.path.expanduser("~"), plan9.MBEFORE|plan9.MCREATE)
この変更は、plan9.bind
関数の第三引数である flags
に plan9.MCREATE
を追加しています。
os.sys.platform == 'plan9'
の条件分岐は、このコードがPlan 9オペレーティングシステム上で実行されている場合にのみ適用されることを示しています。import plan9
は、Plan 9固有のシステムコールをPythonから利用するためのモジュールをインポートしています。os.path.expanduser("~/lib")
は、ユーザーのホームディレクトリ内のlib
ディレクトリへの絶対パスを生成します。os.path.expanduser("~")
は、ユーザーのホームディレクトリへの絶対パスを生成します。plan9.bind(source, destination, flags)
は、source
ディレクトリをdestination
ディレクトリにバインドするPlan 9のシステムコールを呼び出します。- 変更前は
plan9.MBEFORE
のみがフラグとして渡されていました。これは~/lib
の内容が~
の内容より優先されることを意味します。 - 変更後は
plan9.MBEFORE|plan9.MCREATE
となり、ビットごとのOR演算子 (|
) を使ってMBEFORE
とMCREATE
の両方のフラグが結合されています。これにより、~/lib
が~
の前にバインドされるだけでなく、ユニオンされた~
ディレクトリ内で新しいファイルを作成する操作も許可されるようになります。
この修正により、Plan 9環境で codereview.py
がファイルを作成する必要がある場合に、適切なパーミッションと場所でファイルが作成されることが保証されます。
関連リンク
- Go CL 15360045: https://golang.org/cl/15360045
- Plan 9 from Bell Labs 公式サイト: http://plan9.bell-labs.com/plan9/
- Plan 9の
bind
システムコールに関するドキュメント (例:man 2 bind
on Plan 9): http://man.cat-v.org/plan_9/2/bind
参考にした情報源リンク
- Plan 9 from Bell Labs Documentation (特に
bind(2)
manページ) - Goプロジェクトのコードレビューシステムの歴史に関する情報 (Gerrit導入以前の状況)
- Pythonの
os
モジュールに関するドキュメント - ビットごとの演算子に関する一般的なプログラミング知識