diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -381,6 +381,7 @@ 'DifferentialCloseConduitAPIMethod' => 'applications/differential/conduit/DifferentialCloseConduitAPIMethod.php', 'DifferentialCommitMessageCustomField' => 'applications/differential/field/DifferentialCommitMessageCustomField.php', 'DifferentialCommitMessageField' => 'applications/differential/field/DifferentialCommitMessageField.php', + 'DifferentialCommitMessageFieldTestCase' => 'applications/differential/field/__tests__/DifferentialCommitMessageFieldTestCase.php', 'DifferentialCommitMessageParser' => 'applications/differential/parser/DifferentialCommitMessageParser.php', 'DifferentialCommitMessageParserTestCase' => 'applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php', 'DifferentialCommitsField' => 'applications/differential/customfield/DifferentialCommitsField.php', @@ -5030,6 +5031,7 @@ 'DifferentialCloseConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialCommitMessageCustomField' => 'DifferentialCommitMessageField', 'DifferentialCommitMessageField' => 'Phobject', + 'DifferentialCommitMessageFieldTestCase' => 'PhabricatorTestCase', 'DifferentialCommitMessageParser' => 'Phobject', 'DifferentialCommitMessageParserTestCase' => 'PhabricatorTestCase', 'DifferentialCommitsField' => 'DifferentialCustomField', diff --git a/src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php b/src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php --- a/src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php +++ b/src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php @@ -18,8 +18,25 @@ } public function parseFieldValue($value) { - // If the value is just "D123" or similar, parse the ID from it directly. + // If the complete commit message we are parsing has unrecognized custom + // fields at the end, they can end up parsed into the field value for this + // field. For example, if the message looks like this: + + // Differential Revision: xyz + // Some-Other-Field: abc + + // ...we will receive "xyz\nSome-Other-Field: abc" as the field value for + // this field. Ideally, the install would define these fields so they can + // parse formally, but we can reasonably assume that only the first line + // of any value we encounter actually contains a revision identifier, so + // start by throwing away any other lines. + $value = trim($value); + $value = phutil_split_lines($value, false); + $value = head($value); + $value = trim($value); + + // If the value is just "D123" or similar, parse the ID from it directly. $matches = null; if (preg_match('/^[dD]([1-9]\d*)\z/', $value, $matches)) { return (int)$matches[1]; diff --git a/src/applications/differential/field/__tests__/DifferentialCommitMessageFieldTestCase.php b/src/applications/differential/field/__tests__/DifferentialCommitMessageFieldTestCase.php new file mode 100644 --- /dev/null +++ b/src/applications/differential/field/__tests__/DifferentialCommitMessageFieldTestCase.php @@ -0,0 +1,30 @@ + 123, + 'd123' => 123, + " \n d123 \n " => 123, + "D123\nSome-Custom-Field: The End" => 123, + "{$base_uri}D123" => 123, + "{$base_uri}D123\nSome-Custom-Field: The End" => 123, + ); + + $env = PhabricatorEnv::beginScopedEnv(); + $env->overrideEnvConfig('phabricator.base-uri', $base_uri); + + foreach ($tests as $input => $expect) { + $actual = id(new DifferentialRevisionIDCommitMessageField()) + ->parseFieldValue($input); + $this->assertEqual($expect, $actual, pht('Parse of: %s', $input)); + } + + unset($env); + } + +} diff --git a/src/applications/differential/parser/DifferentialCommitMessageParser.php b/src/applications/differential/parser/DifferentialCommitMessageParser.php --- a/src/applications/differential/parser/DifferentialCommitMessageParser.php +++ b/src/applications/differential/parser/DifferentialCommitMessageParser.php @@ -155,7 +155,10 @@ $field = $key_title; $seen = array(); - $lines = explode("\n", trim($corpus)); + + $lines = trim($corpus); + $lines = phutil_split_lines($lines, false); + $field_map = array(); foreach ($lines as $key => $line) { $match = null;