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

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

このコミットは、Go言語プロジェクトのコードレビューシステムにおいて、サブリポジトリ(subrepositories)のサポートを追加するための変更です。具体的には、lib/codereview/codereview.pyファイルが修正され、CONTRIBUTORSファイルの読み込み方法の改善、設定ファイルの処理の柔軟性向上、およびMercurial (hg) コマンドの堅牢性強化が行われています。これにより、Goプロジェクトが複数の独立したリポジトリで構成されている場合でも、一貫したコードレビュープロセスを適用できるようになります。

コミット

codereview: support for subrepositories

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/5564054

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

https://github.com/golang/go/commit/79d2c570438832a09843a01b75b569cf9f31b2bc

元コミット内容

commit 79d2c570438832a09843a01b75b569cf9f31b2bc
Author: Russ Cox <rsc@golang.org>
Date:   Wed Jan 25 14:32:10 2012 -0500

    codereview: support for subrepositories

    R=golang-dev, adg
    CC=golang-dev
    https://golang.org/cl/5564054
---
 lib/codereview/codereview.py | 61 +++++++++++++++++++++++++++++++-------------
 1 file changed, 43 insertions(+), 18 deletions(-)

diff --git a/lib/codereview/codereview.py b/lib/codereview/codereview.py
index 3dbbb72606..6d69d7e2bc 100644
--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -955,14 +955,23 @@ def CheckTabfmt(ui, repo, files, just_warn):
 #######################################################################
 # CONTRIBUTORS file parsing
 
-contributors = {}
+contributorsCache = None
+contributorsURL = None
 
 def ReadContributors(ui, repo):\n-\tglobal contributors
+\tglobal contributorsCache
+\tif contributorsCache is not None:\n+\t\treturn contributorsCache
+\n \ttry:\n-\t\tf = open(repo.root + \'/CONTRIBUTORS\', \'r\')
+\t\tif contributorsURL is not None:\n+\t\t\topening = contributorsURL
+\t\t\tf = urllib2.urlopen(contributorsURL)\n+\t\telse:\n+\t\t\topening = repo.root + \'/CONTRIBUTORS\'\n+\t\t\tf = open(repo.root + \'/CONTRIBUTORS\', \'r\')
 \texcept:\n-\t\tui.write(\"warning: cannot open %s: %s\\n\" % (repo.root+\'/CONTRIBUTORS\', ExceptionDetail()))
+\t\tui.write(\"warning: cannot open %s: %s\\n\" % (opening, ExceptionDetail()))
 \t\treturn
 \n \tfor line in f:\n@@ -980,6 +989,9 @@ def ReadContributors(ui, repo):\n \t\t\tfor extra in m.group(3).split():\n \t\t\t\tcontributors[extra[1:-1].lower()] = (name, email)\n \n+\tcontributorsCache = contributors
+\treturn contributors
+\n def CheckContributor(ui, repo, user=None):\n \tset_status(\"checking CONTRIBUTORS file\")\n \tuser, userline = FindContributor(ui, repo, user, warn=False)\n@@ -997,6 +1009,7 @@ def FindContributor(ui, repo, user=None, warn=True):\n \tif m:\n \t\tuser = m.group(1)\n \n+\tcontributors = ReadContributors(ui, repo)\n \tif user not in contributors:\n \t\tif warn:\n \t\t\tui.warn(\"warning: cannot find %s in CONTRIBUTORS\\n\" % (user,))\n@@ -2163,27 +2176,35 @@ def reposetup(ui, repo):\n \tglobal codereview_disabled\n \tglobal defaultcc\n \t\n+\t# Read repository-specific options from lib/codereview/codereview.cfg or codereview.cfg.\n+\troot = \'\'\n+\ttry:\n+\t\troot = repo.root\n+\texcept:\n+\t\t# Yes, repo might not have root; see issue 959.\n+\t\tcodereview_disabled = \'codereview disabled: repository has no root\'\n+\t\treturn\n+\n \trepo_config_path = \'\'\n-\t# Read repository-specific options from lib/codereview/codereview.cfg\n+\tp1 = root + \'/lib/codereview/codereview.cfg\'\n+\tp2 = root + \'/codereview.cfg\'\n+\tif os.access(p1, os.F_OK):\n+\t\trepo_config_path = p1\n+\telse:\n+\t\trepo_config_path = p2\n \ttry:\n-\t\trepo_config_path = repo.root + \'/lib/codereview/codereview.cfg\'\n \t\tf = open(repo_config_path)\n \t\tfor line in f:\n-\t\t\tif line.startswith(\'defaultcc: \'):\n-\t\t\t\tdefaultcc = SplitCommaSpace(line[10:])
+\t\t\tif line.startswith(\'defaultcc:\'):\n+\t\t\t\tdefaultcc = SplitCommaSpace(line[len(\'defaultcc:\'):])\n+\t\t\tif line.startswith(\'contributors:\'):\n+\t\t\t\tglobal contributorsURL\n+\t\t\t\tcontributorsURL = line[len(\'contributors:\'):].strip()\n \texcept:\n-\t\t# If there are no options, chances are good this is not\n-\t\t# a code review repository; stop now before we foul\n-\t\t# things up even worse.  Might also be that repo doesn\'t\n-\t\t# even have a root.  See issue 959.\n-\t\tif repo_config_path == \'\':\n-\t\t\tcodereview_disabled = \'codereview disabled: repository has no root\'\n-\t\telse:\n-\t\t\tcodereview_disabled = \'codereview disabled: cannot open \' + repo_config_path
+\t\tcodereview_disabled = \'codereview disabled: cannot open \' + repo_config_path\n \t\treturn\n \n \tInstallMatch(ui, repo)\n-\tReadContributors(ui, repo)\n \tRietveldSetup(ui, repo)\n \n \t# Disable the Mercurial commands that might change the repository.\n@@ -3298,7 +3319,11 @@ class MercurialVCS(VersionControlSystem):\n \t\t\tif not err and mqparent != \"\":\n \t\t\t\tself.base_rev = mqparent\n \t\t\telse:\n-\t\t\t\tself.base_rev = RunShell([\"hg\", \"parents\", \"-q\"]).split(\':\')[1].strip()\n+\t\t\t\tout = RunShell([\"hg\", \"parents\", \"-q\"], silent_ok=True).strip()\n+\t\t\t\tif not out:\n+\t\t\t\t\t# No revisions; use 0 to mean a repository with nothing.\n+\t\t\t\t\tout = \"0:0\"\n+\t\t\t\t\tself.base_rev = out.split(\':\')[1].strip()\n \tdef _GetRelPath(self, filename):\n \t\t\"\"\"Get relative path of a file according to the current directory,\n \t\tgiven its logical path in the repo.\"\"\"\n```

## 変更の背景

このコミットの主な背景は、Go言語プロジェクトが複数の独立したリポジトリ(サブリポジトリ)で構成されるようになったことです。Goプロジェクトは、コアのGo言語リポジトリだけでなく、`go.tools`や`go.blog`などの様々な関連プロジェクトを独立したリポジトリとして管理しています。これらのサブリポジリを、メインのGoリポジトリと同じコードレビューシステム(Rietveld)で効率的に管理する必要が生じました。

従来のコードレビューシステムは、単一のモノリシックなリポジトリを前提として設計されていたため、以下のような課題がありました。

1.  **`CONTRIBUTORS`ファイルの管理**: 各サブリポジトリが独自の`CONTRIBUTORS`ファイルを持つ場合や、中央集約された`CONTRIBUTORS`ファイルを共有する場合など、柔軟な読み込み方法が必要でした。特に、`CONTRIBUTORS`ファイルがローカルファイルシステム上だけでなく、URL経由で提供される可能性も考慮する必要がありました。
2.  **リポジトリ固有の設定**: 各サブリポジトリには、デフォルトのCCリスト(`defaultcc`)など、そのリポジトリに固有のコードレビュー設定が必要になる場合があります。これらの設定を、リポジトリのルートディレクトリにある設定ファイルから読み込むメカニズムが必要でした。
3.  **Mercurial (hg) コマンドの堅牢性**: コードレビューツールは、バージョン管理システム(この場合はMercurial)と密接に連携して動作します。特に、コミットの親リビジョンを特定する際に、リポジトリが空である場合や、予期せぬMercurialの出力があった場合に、ツールがクラッシュしないような堅牢性が必要でした。

これらの課題に対処し、Goプロジェクト全体のコードレビュープロセスを円滑にするために、サブリポジトリのサポートが導入されました。

## 前提知識の解説

このコミットを理解するためには、以下の概念について知っておく必要があります。

*   **Go言語プロジェクトの構造**: Go言語プロジェクトは、単一の巨大なリポジトリではなく、複数の独立したリポジトリ(例: `go`、`go.tools`、`go.blog`など)で構成されています。これらは「サブリポジトリ」と呼ばれることがあります。
*   **コードレビュー (Code Review)**: ソフトウェア開発プロセスにおいて、他の開発者が書いたコードをレビューし、品質向上、バグの発見、知識共有などを目的としてフィードバックを与えるプロセスです。Goプロジェクトでは、Rietveldというツールが主要なコードレビューシステムとして使用されていました。
*   **Rietveld**: Googleが開発したWebベースのコードレビューツールです。Perforce、Subversion、Git、Mercurialなどのバージョン管理システムと連携し、変更セット(チェンジリスト)の差分表示、コメントの追加、承認などの機能を提供します。Goプロジェクトでは、初期の頃からRietveldがコードレビューの基盤として利用されていました。
*   **Mercurial (hg)**: 分散型バージョン管理システム(DVCS)の一つで、Gitと同様にリポジトリをローカルに複製して作業を行います。Goプロジェクトは、初期にはMercurialを主要なバージョン管理システムとして採用していました。このコミットが作成された2012年時点では、Goプロジェクトの多くの開発者がMercurialを使用していたと考えられます。
*   **`CONTRIBUTORS`ファイル**: オープンソースプロジェクトでよく見られるファイルで、プロジェクトに貢献した人々のリストとその連絡先情報(通常は名前とメールアドレス)が記載されています。このファイルは、貢献者のクレジットを適切に行うため、また、法的な目的(例: 貢献者ライセンス同意書 (CLA) の確認)のために使用されることがあります。Goプロジェクトのコードレビューシステムでは、コミット者が`CONTRIBUTORS`ファイルに記載されているかどうかを確認するためにこのファイルを参照していました。
*   **`codereview.py`**: Goプロジェクトのコードレビューツールの一部として使用されていたPythonスクリプトです。Rietveldと連携し、ローカルのリポジトリから変更を抽出し、レビューのためにRietveldにアップロードするなどの機能を提供していました。このスクリプトは、Goプロジェクトの特定のコードレビューワークフローに合わせてカスタマイズされていました。
*   **`defaultcc`**: コードレビューにおいて、デフォルトでレビュー担当者として追加される人々のリストを指します。これは、特定の種類の変更や、特定のリポジトリに対する変更に対して、常にレビューが必要なチームや個人を指定するために使用されます。
*   **`urllib2.urlopen`**: Pythonの標準ライブラリ`urllib2`(Python 2.x系)に含まれる関数で、URLを開いてその内容を読み込むために使用されます。これにより、HTTP/HTTPS経由でWebリソースにアクセスできます。

## 技術的詳細

このコミットは、`lib/codereview/codereview.py`ファイルに対して、主に以下の3つの領域で技術的な変更を加えています。

1.  **`CONTRIBUTORS`ファイルの読み込みの柔軟性向上**:
    *   従来の`ReadContributors`関数は、常にローカルの`repo.root + '/CONTRIBUTORS'`パスからファイルを読み込んでいました。
    *   変更後、`contributorsURL`というグローバル変数が導入され、`codereview.cfg`ファイルでこのURLが設定されている場合、`urllib2.urlopen`を使用してそのURLから`CONTRIBUTORS`ファイルを読み込むようになりました。これにより、`CONTRIBUTORS`ファイルがWeb上にホストされている場合でも対応できるようになります。
    *   また、`contributorsCache`というグローバル変数が導入され、一度読み込んだ`CONTRIBUTORS`ファイルの内容をキャッシュするようになりました。これにより、`ReadContributors`関数が複数回呼び出されても、不要なファイルI/Oやネットワークリクエストを避けることができます。
    *   エラーメッセージも、実際に開こうとしたパスまたはURL(`opening`変数)を表示するように改善され、デバッグが容易になりました。

2.  **リポジトリ固有の設定ファイルの処理の改善**:
    *   `reposetup`関数は、リポジトリ固有の設定(例: `defaultcc`)を`codereview.cfg`ファイルから読み込みます。
    *   変更前は、`repo.root + '/lib/codereview/codereview.cfg'`という固定パスのみを試行していました。
    *   変更後、まず`repo.root + '/lib/codereview/codereview.cfg'`を試行し、それが存在しない場合は`repo.root + '/codereview.cfg'`を試行するようになりました。これにより、設定ファイルの配置場所の柔軟性が向上し、サブリポジトリのルートに直接設定ファイルを置くことが可能になります。
    *   `defaultcc`のパースロジックも、`line[10:]`から`line[len('defaultcc:'):]`に変更され、より堅牢になりました。これは、`defaultcc:`の後にスペースが続くかどうかに関わらず、正確に値を抽出するためです。
    *   新たに`contributors:`という設定項目が`codereview.cfg`に追加され、`contributorsURL`グローバル変数にその値を設定できるようになりました。これにより、各サブリポジトリが独自の`CONTRIBUTORS`ファイルのURLを指定できるようになります。
    *   `reposetup`関数内で`ReadContributors`が直接呼び出されていた箇所が削除され、`CheckContributor`などの必要な場所で遅延ロードされるようになりました。

3.  **Mercurial (hg) コマンドの堅牢性強化**:
    *   `MercurialVCS`クラスの`_GetBaseRev`メソッドは、Mercurialの`hg parents -q`コマンドを使用して現在のリビジョンの親リビジョンを取得します。
    *   従来のコードでは、`hg parents -q`の出力が空の場合(例: リポジトリが初期状態である場合)に、`split(':')`がエラーになる可能性がありました。
    *   変更後、`RunShell`に`silent_ok=True`が追加され、コマンドがエラーコードを返しても例外を発生させないようになりました。
    *   `hg parents -q`の出力が空の場合(`not out`)、`"0:0"`という文字列をデフォルトとして使用するようになりました。これは、リポジトリにリビジョンがない状態を意味し、`base_rev`が`"0"`に設定されることで、後続の処理がクラッシュしないようにします。

これらの変更により、Goプロジェクトのコードレビューシステムは、複数のリポジトリにまたがる複雑な開発環境でも、より安定して機能するようになりました。

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

### `lib/codereview/codereview.py`

#### `ReadContributors`関数の変更

```diff
--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -955,14 +955,23 @@ def CheckTabfmt(ui, repo, files, just_warn):
 #######################################################################
 # CONTRIBUTORS file parsing
 
-contributors = {}
+contributorsCache = None
+contributorsURL = None
 
 def ReadContributors(ui, repo):
-\tglobal contributors
+\tglobal contributorsCache
+\tif contributorsCache is not None:\n+\t\treturn contributorsCache
+\n \ttry:\n-\t\tf = open(repo.root + \'/CONTRIBUTORS\', \'r\')
+\t\tif contributorsURL is not None:\n+\t\t\topening = contributorsURL
+\t\t\tf = urllib2.urlopen(contributorsURL)\n+\t\telse:\n+\t\t\topening = repo.root + \'/CONTRIBUTORS\'\n+\t\t\tf = open(repo.root + \'/CONTRIBUTORS\', \'r\')
 \texcept:\n-\t\tui.write(\"warning: cannot open %s: %s\\n\" % (repo.root+\'/CONTRIBUTORS\', ExceptionDetail()))
+\t\tui.write(\"warning: cannot open %s: %s\\n\" % (opening, ExceptionDetail()))
 \t\treturn
 \n \tfor line in f:\n@@ -980,6 +989,9 @@ def ReadContributors(ui, repo):\n \t\t\tfor extra in m.group(3).split():\n \t\t\t\tcontributors[extra[1:-1].lower()] = (name, email)\n \n+\tcontributorsCache = contributors
+\treturn contributors
+\n def CheckContributor(ui, repo, user=None):\
 \tset_status(\"checking CONTRIBUTORS file\")
 \tuser, userline = FindContributor(ui, repo, user, warn=False)\
@@ -997,6 +1009,7 @@ def FindContributor(ui, repo, user=None, warn=True):\
 \tif m:\
 \t\tuser = m.group(1)\
 \n+\tcontributors = ReadContributors(ui, repo)\
 \tif user not in contributors:\
 \t\tif warn:\
 \t\t\tui.warn(\"warning: cannot find %s in CONTRIBUTORS\\n\" % (user,))\

reposetup関数の変更

--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -2163,27 +2176,35 @@ def reposetup(ui, repo):
 \tglobal codereview_disabled
 \tglobal defaultcc
 \t\
+\t# Read repository-specific options from lib/codereview/codereview.cfg or codereview.cfg.\
+\troot = \'\'\
+\ttry:\n+\t\troot = repo.root\n+\texcept:\n+\t\t# Yes, repo might not have root; see issue 959.\n+\t\tcodereview_disabled = \'codereview disabled: repository has no root\'\n+\t\treturn\n+\n \trepo_config_path = \'\'\
-\t# Read repository-specific options from lib/codereview/codereview.cfg
+\tp1 = root + \'/lib/codereview/codereview.cfg\'\n+\tp2 = root + \'/codereview.cfg\'\n+\tif os.access(p1, os.F_OK):\n+\t\trepo_config_path = p1\n+\telse:\n+\t\trepo_config_path = p2\
 \ttry:\
-\t\trepo_config_path = repo.root + \'/lib/codereview/codereview.cfg\'
 \t\tf = open(repo_config_path)\
 \t\tfor line in f:\
-\t\t\tif line.startswith(\'defaultcc: \'):\
-\t\t\t\tdefaultcc = SplitCommaSpace(line[10:])
+\t\t\tif line.startswith(\'defaultcc:\'):\n+\t\t\t\tdefaultcc = SplitCommaSpace(line[len(\'defaultcc:\'):])\n+\t\t\tif line.startswith(\'contributors:\'):\n+\t\t\t\tglobal contributorsURL\n+\t\t\t\tcontributorsURL = line[len(\'contributors:\'):].strip()\
 \texcept:\
-\t\t# If there are no options, chances are good this is not\n-\t\t# a code review repository; stop now before we foul\n-\t\t# things up even worse.  Might also be that repo doesn\'t\n-\t\t# even have a root.  See issue 959.\n-\t\tif repo_config_path == \'\':\n-\t\t\tcodereview_disabled = \'codereview disabled: repository has no root\'\n-\t\telse:\n-\t\t\tcodereview_disabled = \'codereview disabled: cannot open \' + repo_config_path
+\t\tcodereview_disabled = \'codereview disabled: cannot open \' + repo_config_path\
 \t\treturn
 \n \tInstallMatch(ui, repo)\
-\tReadContributors(ui, repo)\
 \tRietveldSetup(ui, repo)\
 \n \t# Disable the Mercurial commands that might change the repository.\

MercurialVCSクラスの_GetBaseRevメソッドの変更

--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -3298,7 +3319,11 @@ class MercurialVCS(VersionControlSystem):
 \t\t\tif not err and mqparent != \"\":
 \t\t\t\tself.base_rev = mqparent
 \t\t\telse:\
-\t\t\t\tself.base_rev = RunShell([\"hg\", \"parents\", \"-q\"]).split(\':\')[1].strip()\
+\t\t\t\tout = RunShell([\"hg\", \"parents\", \"-q\"], silent_ok=True).strip()\n+\t\t\t\tif not out:\n+\t\t\t\t\t# No revisions; use 0 to mean a repository with nothing.\n+\t\t\t\t\tout = \"0:0\"\n+\t\t\t\t\tself.base_rev = out.split(\':\')[1].strip()\
 \tdef _GetRelPath(self, filename):\
 \t\t\"\"\"Get relative path of a file according to the current directory,\
 \t\tgiven its logical path in the repo.\"\"\"\

コアとなるコードの解説

ReadContributors関数の変更

  • contributorsCache = NonecontributorsURL = None の追加:
    • contributorsCacheは、CONTRIBUTORSファイルの内容を一度読み込んだらキャッシュするための変数です。これにより、同じセッション内で何度もReadContributorsが呼び出されても、ファイルI/Oやネットワークリクエストを繰り返す無駄を省きます。
    • contributorsURLは、CONTRIBUTORSファイルがローカルパスではなく、Web上のURLとして指定された場合にそのURLを保持するための変数です。
  • キャッシュの利用 (if contributorsCache is not None: return contributorsCache):
    • 関数が呼び出された際に、まずcontributorsCacheNoneでないか(つまり、既にデータがキャッシュされているか)を確認します。キャッシュされていれば、すぐにその内容を返して処理を終了します。
  • URLからの読み込みサポート (if contributorsURL is not None: ... f = urllib2.urlopen(contributorsURL)):
    • contributorsURLが設定されている場合、urllib2.urlopenを使用して指定されたURLからCONTRIBUTORSファイルを読み込みます。これにより、CONTRIBUTORSファイルがWebサービスとして提供されているようなシナリオに対応できます。
  • ローカルファイルからの読み込み (else: ... f = open(repo.root + '/CONTRIBUTORS', 'r')):
    • contributorsURLが設定されていない場合は、従来通りローカルのrepo.root + '/CONTRIBUTORS'パスからファイルを読み込みます。
  • エラーメッセージの改善:
    • try...exceptブロック内で、開こうとしたパスまたはURLをopening変数に格納し、エラーメッセージにそのopening変数を表示するように変更されました。これにより、エラー発生時にどのリソースへのアクセスに失敗したのかが明確になります。
  • キャッシュへの保存 (contributorsCache = contributors):
    • CONTRIBUTORSファイルの内容を読み込み、パースしてcontributors辞書に格納した後、そのcontributors辞書をcontributorsCacheに代入してキャッシュします。
  • CheckContributorでのReadContributors呼び出し:
    • CheckContributor関数内で、contributors変数を初期化する際にReadContributors(ui, repo)を呼び出すように変更されました。これにより、CONTRIBUTORSデータが必要になった時点で初めて読み込まれるようになり、不要な早期ロードが避けられます。

reposetup関数の変更

  • リポジトリルートの取得の堅牢化:
    • root = ''で初期化し、try...exceptブロックでrepo.rootを取得するように変更されました。これは、repoオブジェクトがroot属性を持たない場合(Issue 959で報告されたようなケース)に、ツールがクラッシュするのを防ぐためです。
  • 設定ファイルのパスの柔軟性向上:
    • p1 = root + '/lib/codereview/codereview.cfg'p2 = root + '/codereview.cfg'という2つのパスを定義します。
    • os.access(p1, os.F_OK)p1が存在するかを確認し、存在すればrepo_config_pathp1を設定します。存在しない場合はp2を設定します。これにより、設定ファイルがlib/codereview/サブディレクトリにある場合と、リポジトリのルートにある場合の両方に対応できるようになります。
  • defaultccのパースロジックの改善:
    • line.startswith('defaultcc: ')からline.startswith('defaultcc:')に変更され、値の抽出もline[10:]からline[len('defaultcc:'):]に変更されました。これにより、defaultcc:の後にスペースが続くかどうかに関わらず、正確に値を抽出できるようになります。
  • contributors:設定項目の追加:
    • if line.startswith('contributors:'):という条件が追加され、codereview.cfgファイルにcontributors: <URL>のような行がある場合、そのURLをcontributorsURLグローバル変数に設定します。これにより、各サブリポジトリが独自のCONTRIBUTORSファイルの場所を外部から指定できるようになります。
  • エラーハンドリングの簡素化:
    • 以前の複雑なエラーハンドリング(repo_config_path == ''のチェックなど)が削除され、単にcodereview_disabled = 'codereview disabled: cannot open ' + repo_config_pathというメッセージを設定するように簡素化されました。
  • ReadContributorsの直接呼び出しの削除:
    • reposetup関数の最後で直接ReadContributors(ui, repo)を呼び出していた行が削除されました。これにより、CONTRIBUTORSデータの読み込みは、実際に必要になった時点(例: CheckContributorが呼び出された時)まで遅延されます。

MercurialVCSクラスの_GetBaseRevメソッドの変更

  • RunShellsilent_ok=Trueオプションの追加:
    • RunShell(["hg", "parents", "-q"])の呼び出しにsilent_ok=Trueが追加されました。これは、Mercurialコマンドがエラーコードを返しても、Pythonスクリプトが例外を発生させずに、その出力を返すように指示します。これにより、hg parents -qが空のリポジトリでエラーを返すような場合でも、ツールがクラッシュするのを防ぎます。
  • 空のリポジトリのハンドリング:
    • out = RunShell(...)の実行後、if not out:という条件で、hg parents -qの出力が空文字列であるかどうかを確認します。
    • 出力が空の場合、out = "0:0"という文字列を代入します。これは、Mercurialのリビジョン形式(例: リビジョン番号:ハッシュ)に合わせたもので、リビジョンがない状態を0として表現します。
    • これにより、続くout.split(':')[1].strip()の処理が常に有効な文字列に対して行われ、インデックスエラーを防ぎます。結果として、リポジトリが空の場合のbase_rev"0"になります。

これらの変更は、Goプロジェクトのコードレビューシステムが、より多様なリポジトリ構成とMercurialの挙動に対応できるよう、堅牢性と柔軟性を高めることを目的としています。

関連リンク

参考にした情報源リンク