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

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

このコミットは、Goプロジェクトのコードレビューシステムにおける、Mercurial (hg) の同期処理に関するバグ修正です。具体的には、サブモジュール(subrepositories)に対する変更リスト(Change List, CL)が、自身によって提出されたものの、他の開発者によってコミットされた場合に、正しくクローズされない問題を解決します。

コミット

commit 50d4dae80b9afc34dc931caef180161dba9b1530
Author: Dominik Honnef <dominik.honnef@gmail.com>
Date:   Thu Oct 10 16:30:47 2013 -0700

    codereview: fix hg sync closing of CLs for subrepositories
    
    The regexp for closing CLs that were sent by you but committed by
    someone else only matched messages for the main repository,
    because of the added &repo=... for subrepositories.
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/14512045

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

https://github.com/golang/go/commit/50d4dae80b9afc34dc931caef180161dba9b1530

元コミット内容

codereview: fix hg sync closing of CLs for subrepositories

The regexp for closing CLs that were sent by you but committed by
someone else only matched messages for the main repository,
because of the added &repo=... for subrepositories.

変更の背景

Goプロジェクトでは、コードレビューにRietveldというシステムが使用されていました(現在はGerritに移行済み)。開発者は変更をRietveldにアップロードし、レビューを受け、承認された後にコミットされます。このプロセスにおいて、自身が提出した変更リスト(CL)が、他の開発者(例えば、メンテナー)によって最終的にリポジトリにコミットされることがあります。

このコミットが修正しようとしている問題は、hg sync(Mercurialの同期コマンド)が実行された際に、Rietveld上のCLのステータスを正しく更新できないというものでした。特に、サブモジュール(subrepositories)に対する変更の場合に問題が発生していました。

Rietveldは、CLがコミットされたことを示すために、レビューコメントに特定の形式のメッセージを追加します。このメッセージには、コミットハッシュが含まれており、codereview.pyスクリプトがこのメッセージを解析して、CLがコミット済みであると判断し、ステータスを「クローズ済み」に更新します。

しかし、サブモジュールに対する変更の場合、Rietveldのメッセージには&repo=...という形式のクエリパラメータが追加されることがありました。既存の正規表現は、この&repo=...の部分を考慮していなかったため、サブモジュールに対するCLがコミットされても、正規表現がマッチせず、CLがRietveld上で「オープン」のまま残ってしまうというバグがありました。これにより、開発者は自分のCLが既にコミットされているにもかかわらず、Rietveld上では未処理のように見えてしまうという不便を強いられていました。

前提知識の解説

  • Goプロジェクトのコードレビュープロセス: Goプロジェクトは、かつてRietveldというコードレビューツールを使用していました。開発者は変更をRietveldにアップロードし、レビューアからのフィードバックを受け、最終的に承認された変更がリポジトリにコミットされます。このプロセスでは、開発者自身がコミットすることもあれば、メンテナーが代理でコミットすることもあります。
  • Rietveld: Googleが開発したオープンソースのコードレビューシステムです。PerforceのChange List (CL) の概念に影響を受けています。ウェブベースのインターフェースを提供し、コードの差分表示、コメント、ステータス管理などの機能を提供します。
  • Change List (CL): Rietveldにおける変更の単位です。一連の変更(コミット)をまとめてレビューに提出する際に使用されます。
  • Mercurial (hg): 分散型バージョン管理システムの一つで、Gitと同様の機能を提供します。Goプロジェクトは初期にはMercurialを使用していましたが、後にGitに移行しました。hg syncは、ローカルリポジトリとリモートリポジトリ間で変更を同期するためのコマンドです。
  • サブモジュール (Subrepositories): Mercurialにおける機能で、一つのリポジトリ内に別のリポジトリを埋め込むことができます。これにより、複数の関連するプロジェクトを一つの親リポジトリで管理することが可能になります。Goプロジェクトでは、標準ライブラリの一部やツールなどがサブモジュールとして管理されることがありました。
  • 正規表現 (Regular Expression, Regexp): 文字列のパターンを記述するための強力なツールです。このコミットでは、Rietveldのコメントから特定の情報を抽出するために正規表現が使用されています。
    • re.match(): Pythonのreモジュールにおける関数で、文字列の先頭から正規表現パターンにマッチするかどうかを調べます。
    • *: 直前の文字が0回以上繰り返されることを意味します。
    • ?: 直前の文字が0回または1回出現することを意味します(非貪欲マッチ)。
    • [^*]*?: *以外の任意の文字が0回以上繰り返されることを非貪欲にマッチさせます。
    • [0-9a-f]+: 16進数の文字(0-9, a-f)が1回以上繰り返されることを意味します。これはコミットハッシュの一部を捕捉するために使用されます。
    • \s: 空白文字にマッチします。
    • \*\*\*: *は正規表現の特殊文字なので、リテラルとしてマッチさせるためにはエスケープ(\)が必要です。

技術的詳細

このコミットの核心は、lib/codereview/codereview.pyファイル内のIsRietveldSubmitted関数における正規表現の変更です。この関数は、Rietveldのメッセージを解析し、特定のCLが既にコミットされているかどうかを判断する役割を担っています。

元の正規表現は以下の通りでした。 re.match('\\*\\*\\* Submitted as [^*]*?([0-9a-f]+) \\*\\*\\*'

この正規表現は、Rietveldのコメントが「*** Submitted as <何か> <コミットハッシュ> ***」という形式であると想定していました。ここで<何か>の部分は、コミットハッシュの前に来る任意の文字列(*以外の文字)に非貪欲にマッチします。そして、([0-9a-f]+)でコミットハッシュをキャプチャしていました。

しかし、サブモジュールに対するCLがコミットされた場合、Rietveldのコメントは例えば「*** Submitted as <何か> r=<コミットハッシュ>&repo=subrepo_name ***」のように、コミットハッシュの後に&repo=...という形式の文字列が追加されることがありました。元の正規表現は、この&repo=...の部分を正しく処理できず、マッチに失敗していました。具体的には、[^*]*?の部分が&repo=を含む文字列全体を消費してしまい、その後の([0-9a-f]+)がコミットハッシュを正しく抽出できなかったか、あるいは***の閉じタグがマッチしなかった可能性があります。

新しい正規表現は以下の通りです。 re.match('\\*\\*\\* Submitted as [^*]*?r=([0-9a-f]+)[^ ]* \\*\\*\\*'

この変更のポイントは、コミットハッシュをキャプチャする部分の直前にr=を追加し、その後に[^ ]*(スペース以外の任意の文字が0回以上繰り返される)を追加したことです。

  • r=: Rietveldのコメントでコミットハッシュの前にr=が付与されるパターンに対応します。これは、Rietveldがコミットハッシュを識別するためのプレフィックスとして使用していた可能性があります。
  • ([^ ]*): コミットハッシュの後に続く、スペース以外の任意の文字(&repo=...など)にマッチします。これにより、&repo=...のような追加情報があっても、正規表現全体が正しくマッチし、([0-9a-f]+)が正確にコミットハッシュをキャプチャできるようになります。

この修正により、サブモジュールに対するCLがコミットされた場合でも、hg syncがRietveldのコメントを正しく解析し、CLのステータスを「クローズ済み」に更新できるようになりました。

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

lib/codereview/codereview.pyファイルのIsRietveldSubmitted関数内の正規表現が変更されています。

--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -2402,7 +2402,7 @@ def IsRietveldSubmitted(ui, clname, hex):
 		return False
 	for msg in dict.get("messages", []):
 		text = msg.get("text", "")
-		m = re.match('\\*\\*\\* Submitted as [^*]*?([0-9a-f]+) \\*\\*\\*', text)
+		m = re.match('\\*\\*\\* Submitted as [^*]*?r=([0-9a-f]+)[^ ]* \\*\\*\\*', text)
 		if m is not None and len(m.group(1)) >= 8 and hex.startswith(m.group(1)):
 			return True
 	return False

コアとなるコードの解説

IsRietveldSubmitted関数は、与えられたclname(Change Listの名前)とhex(コミットハッシュ)がRietveldによって提出されたものかどうかを判断します。

  1. dict.get("messages", [])で、RietveldのCLに関連付けられたメッセージのリストを取得します。
  2. 各メッセージ(msg)について、そのテキスト内容(text)を取得します。
  3. re.match()を使用して、メッセージテキストが特定のパターンにマッチするかどうかをチェックします。
    • 変更前: re.match('\\*\\*\\* Submitted as [^*]*?([0-9a-f]+) \\*\\*\\*', text)
    • 変更後: re.match('\\*\\*\\* Submitted as [^*]*?r=([0-9a-f]+)[^ ]* \\*\\*\\*', text) この正規表現は、メッセージが「*** Submitted as ...」で始まり、その中にコミットハッシュ([0-9a-f]+)が含まれていることを期待します。
  4. m is not Noneでマッチが成功したかどうかを確認します。
  5. len(m.group(1)) >= 8で、キャプチャされたコミットハッシュの長さが8文字以上であることを確認します。これは、コミットハッシュが十分に長いことを保証するためです。
  6. hex.startswith(m.group(1))で、与えられたコミットハッシュhexが、メッセージから抽出されたコミットハッシュのプレフィックスと一致するかどうかを確認します。これは、部分的なハッシュマッチを許容するためです。
  7. これらの条件がすべて満たされれば、そのCLはRietveldによって提出され、コミットされたものと判断し、Trueを返します。

この修正により、正規表現がサブモジュールに関連するRietveldのコメント形式にも対応できるようになり、hg syncがCLのステータスを正確に更新できるようになりました。

関連リンク

参考にした情報源リンク

  • GoプロジェクトのGitHubリポジトリ: https://github.com/golang/go
  • Mercurialのサブモジュールに関するドキュメント
  • 正規表現に関する一般的なドキュメント(Pythonのreモジュールなど)
  • Rietveldのコメント形式に関する情報(Goプロジェクトの過去のコードレビュー慣習)
  • コミットメッセージとコードの差分 I have provided the detailed explanation as requested, following all the specified instructions and chapter structure. I have used the commit information and general knowledge about Go's past development practices (Rietveld, Mercurial) to provide a comprehensive explanation. I did not need to use google_web_search explicitly as the context from the commit message and my existing knowledge was sufficient to explain the technical details.

I have outputted the explanation to standard output only, as requested. The task is complete.