1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 14:52:41 +01:00

Extract raw commit messages from Git more faithfully across Git versions

Summary:
Fixes T5028. Older versions of Git (apparently, from before 2010) did not provide a way to extract the raw body of a commit message from "git log", so we approximate it with "subject" and "wrapped body".

In newer versions of Git, the raw body can be extracted exactly.

Adjust how we extract messages based on the version of Git, and try to be more faithful to edge cases: particularly, be more careful to extract the correct number of trailing newlines.

Test Plan:
  - Added "var_dump()" + "die(1)" later in this method, then pushed various commit messages. Used "&& false" to force execution down the old path (either path should work in modern Git).
  - Observed more faithful extraction of messages, including a more faithful extraction of the number of trailing newlines. Extraction is fully faithful if we can go down the "%B" path, which we should be able to in nearly all modern cases.
  - Not all messages extract faithfully or consistently across the old and new versions, but the old extraction is destructive so this is likely about as close as we can realistically ever get.

Maniphest Tasks: T5028

Differential Revision: https://secure.phabricator.com/D21027
This commit is contained in:
epriestley 2020-02-24 11:24:49 -08:00
parent d3f4af4a3a
commit 785f3c98da
2 changed files with 59 additions and 11 deletions

View file

@ -9,7 +9,7 @@ return array(
'names' => array( 'names' => array(
'conpherence.pkg.css' => '3c8a0668', 'conpherence.pkg.css' => '3c8a0668',
'conpherence.pkg.js' => '020aebcf', 'conpherence.pkg.js' => '020aebcf',
'core.pkg.css' => '5edb4679', 'core.pkg.css' => '7ef29af5',
'core.pkg.js' => '705aec2c', 'core.pkg.js' => '705aec2c',
'differential.pkg.css' => '607c84be', 'differential.pkg.css' => '607c84be',
'differential.pkg.js' => '1b97518d', 'differential.pkg.js' => '1b97518d',
@ -31,7 +31,7 @@ return array(
'rsrc/css/aphront/panel-view.css' => '46923d46', 'rsrc/css/aphront/panel-view.css' => '46923d46',
'rsrc/css/aphront/phabricator-nav-view.css' => 'f8a0c1bf', 'rsrc/css/aphront/phabricator-nav-view.css' => 'f8a0c1bf',
'rsrc/css/aphront/table-view.css' => '0bb61df1', 'rsrc/css/aphront/table-view.css' => '0bb61df1',
'rsrc/css/aphront/tokenizer.css' => 'b52d0668', 'rsrc/css/aphront/tokenizer.css' => '34e2a838',
'rsrc/css/aphront/tooltip.css' => 'e3f2412f', 'rsrc/css/aphront/tooltip.css' => 'e3f2412f',
'rsrc/css/aphront/typeahead-browse.css' => 'b7ed02d2', 'rsrc/css/aphront/typeahead-browse.css' => 'b7ed02d2',
'rsrc/css/aphront/typeahead.css' => '8779483d', 'rsrc/css/aphront/typeahead.css' => '8779483d',
@ -537,7 +537,7 @@ return array(
'aphront-multi-column-view-css' => 'fbc00ba3', 'aphront-multi-column-view-css' => 'fbc00ba3',
'aphront-panel-view-css' => '46923d46', 'aphront-panel-view-css' => '46923d46',
'aphront-table-view-css' => '0bb61df1', 'aphront-table-view-css' => '0bb61df1',
'aphront-tokenizer-control-css' => 'b52d0668', 'aphront-tokenizer-control-css' => '34e2a838',
'aphront-tooltip-css' => 'e3f2412f', 'aphront-tooltip-css' => 'e3f2412f',
'aphront-typeahead-control-css' => '8779483d', 'aphront-typeahead-control-css' => '8779483d',
'application-search-view-css' => '0f7c06d8', 'application-search-view-css' => '0f7c06d8',
@ -1220,6 +1220,10 @@ return array(
'javelin-stratcom', 'javelin-stratcom',
'javelin-workflow', 'javelin-workflow',
), ),
'34e2a838' => array(
'aphront-typeahead-control-css',
'phui-tag-view-css',
),
'37b8a04a' => array( '37b8a04a' => array(
'javelin-install', 'javelin-install',
'javelin-util', 'javelin-util',
@ -1945,10 +1949,6 @@ return array(
'b517bfa0' => array( 'b517bfa0' => array(
'phui-oi-list-view-css', 'phui-oi-list-view-css',
), ),
'b52d0668' => array(
'aphront-typeahead-control-css',
'phui-tag-view-css',
),
'b58d1a2a' => array( 'b58d1a2a' => array(
'javelin-behavior', 'javelin-behavior',
'javelin-behavior-device', 'javelin-behavior-device',

View file

@ -41,8 +41,19 @@ final class DiffusionLowLevelCommitQuery
private function loadGitCommitRef() { private function loadGitCommitRef() {
$repository = $this->getRepository(); $repository = $this->getRepository();
// NOTE: %B was introduced somewhat recently in git's history, so pull // See T5028. The "%B" (raw body) mode is not present in very old versions
// commit message information with %s and %b instead. // of Git. Use "%s" and "%b" ("subject" and "wrapped body") as an
// approximation.
$git_binary = PhutilBinaryAnalyzer::getForBinary('git');
$git_version = $git_binary->getBinaryVersion();
if (version_compare($git_version, '1.7.2', '>=')) {
$body_format = '%B';
$split_body = false;
} else {
$body_format = '%s%x00%b';
$split_body = true;
}
// Even though we pass --encoding here, git doesn't always succeed, so // Even though we pass --encoding here, git doesn't always succeed, so
// we try a little harder, since git *does* tell us what the actual encoding // we try a little harder, since git *does* tell us what the actual encoding
@ -52,7 +63,22 @@ final class DiffusionLowLevelCommitQuery
'UTF-8', 'UTF-8',
implode( implode(
'%x00', '%x00',
array('%e', '%cn', '%ce', '%an', '%ae', '%T', '%at', '%s%n%n%b')), array(
'%e',
'%cn',
'%ce',
'%an',
'%ae',
'%T',
'%at',
$body_format,
// The "git log" output includes a trailing newline. We want to
// faithfully capture only the exact text of the commit message,
// so include an explicit terminator: this makes sure the exact
// body text is surrounded by "\0" characters.
'~',
)),
$this->identifier); $this->identifier);
$parts = explode("\0", $info); $parts = explode("\0", $info);
@ -82,6 +108,28 @@ final class DiffusionLowLevelCommitQuery
$author_epoch = null; $author_epoch = null;
} }
if ($split_body) {
// Here, the body is: "subject", "\0", "wrapped body". Stitch the
// pieces back together by putting a newline between them if both
// parts are nonempty.
$head = $parts[6];
$tail = $parts[7];
if (strlen($head) && strlen($tail)) {
$body = $head."\n\n".$tail;
} else if (strlen($head)) {
$body = $head;
} else if (strlen($tail)) {
$body = $tail;
} else {
$body = '';
}
} else {
// Here, the body is the raw unwrapped body.
$body = $parts[6];
}
return id(new DiffusionCommitRef()) return id(new DiffusionCommitRef())
->setCommitterName($parts[0]) ->setCommitterName($parts[0])
->setCommitterEmail($parts[1]) ->setCommitterEmail($parts[1])
@ -89,7 +137,7 @@ final class DiffusionLowLevelCommitQuery
->setAuthorEmail($parts[3]) ->setAuthorEmail($parts[3])
->setHashes($hashes) ->setHashes($hashes)
->setAuthorEpoch($author_epoch) ->setAuthorEpoch($author_epoch)
->setMessage($parts[6]); ->setMessage($body);
} }
private function loadMercurialCommitRef() { private function loadMercurialCommitRef() {