Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 17487] ファイルの概要

このコミットは、Goプロジェクトのコードレビューツール codereview.py における、Mercurial 2.7への対応に関する変更です。具体的には、Mercurialの promptchoice 関数の使用方法がバージョン2.7で変更されたことに伴い、既存のコードが正しく動作するように修正されています。

コミット

commit 8f764fb689ea4313c5a6de2cabdf65aee9f89c5d
Author: Anthony Martin <ality@pbrane.org>
Date:   Fri Sep 6 15:48:21 2013 -0400

    codereview: update use of promptchoice for Mercurial 2.7
    
    Fixes #6186.
    
    R=golang-dev, bradfitz, remyoudompheng, rsc
    CC=golang-dev
    https://golang.org/cl/13112043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/8f764fb689ea4313c5a6de2cabdf65aee9f89c5d

元コミット内容

codereview: update use of promptchoice for Mercurial 2.7

Fixes #6186.

R=golang-dev, bradfitz, remyoudompheng, rsc
CC=golang-dev
https://golang.org/cl/13112043

変更の背景

この変更は、Goプロジェクトのコードレビューシステムが依存しているバージョン管理システムであるMercurialのバージョン2.7における変更に対応するために行われました。Mercurial 2.7では、対話型プロンプトを表示するための promptchoice 関数の引数形式が変更されました。

Goプロジェクトでは、コードレビュープロセスを自動化・効率化するために codereview.py というPythonスクリプトを使用しています。このスクリプトは、Mercurialコマンドを内部的に呼び出し、ユーザーからの入力を promptchoice のようなMercurialのUI関数を通じて受け取っていました。Mercurial 2.7へのアップグレードにより、promptchoice の呼び出し方が古くなり、スクリプトが正しく動作しなくなる問題が発生しました。

コミットメッセージにある Fixes #6186 は、この変更がGoプロジェクトのIssueトラッカーで報告されたバグ #6186 を修正するものであることを示しています。このバグは、Mercurial 2.7環境でコードレビューツールが機能しないという問題であったと推測されます。

前提知識の解説

Mercurial (Hg)

Mercurialは、分散型バージョン管理システム(DVCS)の一つです。Gitと同様に、各開発者がコードベースの完全な履歴をローカルに持ち、オフラインでの作業やブランチの作成・マージが容易に行えます。Goプロジェクトは、初期にはMercurialを主要なバージョン管理システムとして利用していました。

promptchoice 関数

Mercurialの内部には、ユーザーとの対話を行うためのUI(ユーザーインターフェース)関数群が存在します。promptchoice はその一つで、ユーザーに複数の選択肢を提示し、その中から一つを選ばせるための関数です。例えば、「変更をコミットしますか? (y/n)」といった質問に対して、ユーザーが y または n を入力するようなシナリオで利用されます。

codereview.py

codereview.py は、Goプロジェクトが独自に開発したコードレビュー支援ツールです。このツールは、Mercurialリポジトリと連携し、変更セットの作成、レビューサーバーへのアップロード、レビューコメントの取得、変更の適用など、コードレビューワークフローを効率化するための機能を提供していました。Pythonで書かれており、MercurialのPython APIを利用してMercurialの操作を行っていました。

バージョン管理システムの互換性問題

ソフトウェア開発において、依存するライブラリやツールのバージョンアップは頻繁に発生します。これらのバージョンアップには、APIの変更や非推奨化が含まれることがあり、それによって既存のコードが動作しなくなる「互換性問題」が発生することがあります。本コミットは、まさにMercurialのAPI変更によって引き起こされた互換性問題に対処する典型的な例です。

技術的詳細

Mercurial 2.7における promptchoice 関数の変更は、その引数形式にありました。以前のバージョンでは、選択肢のリストを直接引数として渡す形式でしたが、Mercurial 2.7からは、メッセージ文字列の中に選択肢を特殊な形式で埋め込む形式に変更されました。

具体的には、Mercurial 2.7以降では、promptchoice のメッセージ文字列内に $$ &yes $$ &no のように $$ で囲まれた選択肢を含めることで、ユーザーに提示する選択肢を定義するようになりました。これにより、promptchoice の呼び出し側は、メッセージと選択肢を単一の文字列として渡すことになります。

この変更は、MercurialのUIレイヤーの内部的な設計変更によるものと考えられます。おそらく、より柔軟なプロンプト表示や、国際化対応などを考慮した結果、このような形式になったと推測されます。

codereview.py は、MercurialのPython APIを通じて ui.promptchoice を呼び出していました。Mercurial 2.7へのアップグレード後、codereview.py が古い引数形式で promptchoice を呼び出すと、Mercurialはそれを認識できず、エラーとなるか、意図しない動作を引き起こしていました。

このコミットでは、hgversion という変数を用いてMercurialのバージョンをチェックし、バージョン2.7以上の場合とそれ未満の場合で promptchoice の呼び出し方を分岐させることで、この互換性問題を解決しています。

コアとなるコードの変更箇所

変更は lib/codereview/codereview.py ファイルの promptyesno 関数にあります。

--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -712,7 +712,10 @@ Examples:
 ''''

 def promptyesno(ui, msg):
-	return ui.promptchoice(msg, ["&yes", "&no"], 0) == 0
+	if hgversion >= "2.7":
+		return ui.promptchoice(msg + " $$ &yes $$ &no", 0) == 0
+	else:
+		return ui.promptchoice(msg, ["&yes", "&no"], 0) == 0

 def promptremove(ui, repo, f):
  if promptyesno(ui, "hg remove %s (y/n)?" % (f,)):

コアとなるコードの解説

promptyesno 関数は、ユーザーに「はい/いいえ」の選択肢を提示し、その結果をブール値で返すヘルパー関数です。

変更前は、以下のコードでした。

def promptyesno(ui, msg):
	return ui.promptchoice(msg, ["&yes", "&no"], 0) == 0

ここでは、ui.promptchoice に対して、メッセージ msg と、選択肢のリスト ["&yes", "&no"]、そしてデフォルトの選択肢のインデックス 0 (つまり "yes") を渡していました。

変更後は、Mercurialのバージョンをチェックする条件分岐が追加されています。

def promptyesno(ui, msg):
	if hgversion >= "2.7":
		return ui.promptchoice(msg + " $$ &yes $$ &no", 0) == 0
	else:
		return ui.promptchoice(msg, ["&yes", ["&no"], 0) == 0
  • if hgversion >= "2.7":
    • この条件は、現在実行されているMercurialのバージョンが2.7以上であるかどうかをチェックしています。hgversion は、codereview.py のどこかでMercurialのバージョン情報を取得して設定されているグローバル変数またはモジュール変数であると推測されます。
    • バージョンが2.7以上の場合、ui.promptchoice の呼び出し方が変更されています。
      • msg + " $$ &yes $$ &no": メッセージ文字列 msg の後ろに、新しい形式の選択肢文字列 " $$ &yes $$ &no" を連結しています。これにより、promptchoice は単一の文字列からメッセージと選択肢の両方を解析するようになります。
      • 0: デフォルトの選択肢のインデックスは引き続き 0 です。
  • else:
    • Mercurialのバージョンが2.7未満の場合(つまり、古いバージョン)、以前と同じ ui.promptchoice(msg, ["&yes", "&no"], 0) の呼び出し方が維持されます。

この変更により、codereview.py はMercurialのバージョンに依存せず、異なるバージョンのMercurial環境でも promptyesno 関数が正しく動作するようになりました。これは、後方互換性を維持しつつ、新しいバージョンのMercurialにも対応するための一般的なプログラミングパターンです。

関連リンク

参考にした情報源リンク