mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-25 16:22:42 +01:00
Pre-fill template fields under "arc diff --create" in git
Summary: When the user runs "arc diff --create" or triggers it via "arc diff --auto", prefill the template as best we can. Test Plan: Ran "arc diff --auto" with a template commit message in the working copy under various configurations, results seemed reasonable. Reviewers: btrahan Reviewed By: btrahan CC: aran, epriestley, dmi Maniphest Tasks: T614 Differential Revision: https://secure.phabricator.com/D1719
This commit is contained in:
parent
1f13e022cd
commit
2fa18d80f8
3 changed files with 108 additions and 36 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,3 +3,4 @@
|
||||||
/src/.phutil_module_cache
|
/src/.phutil_module_cache
|
||||||
/docs/
|
/docs/
|
||||||
/.divinercache/
|
/.divinercache/
|
||||||
|
/.arc/
|
||||||
|
|
|
@ -25,7 +25,7 @@ final class ArcanistDifferentialCommitMessage {
|
||||||
|
|
||||||
private $rawCorpus;
|
private $rawCorpus;
|
||||||
private $revisionID;
|
private $revisionID;
|
||||||
private $fields;
|
private $fields = array();
|
||||||
|
|
||||||
private $gitSVNBaseRevision;
|
private $gitSVNBaseRevision;
|
||||||
private $gitSVNBasePath;
|
private $gitSVNBasePath;
|
||||||
|
@ -78,17 +78,25 @@ final class ArcanistDifferentialCommitMessage {
|
||||||
return $this->revisionID;
|
return $this->revisionID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pullDataFromConduit(ConduitClient $conduit) {
|
public function pullDataFromConduit(
|
||||||
|
ConduitClient $conduit,
|
||||||
|
$partial = false) {
|
||||||
|
|
||||||
$result = $conduit->callMethodSynchronous(
|
$result = $conduit->callMethodSynchronous(
|
||||||
'differential.parsecommitmessage',
|
'differential.parsecommitmessage',
|
||||||
array(
|
array(
|
||||||
'corpus' => $this->rawCorpus,
|
'corpus' => $this->rawCorpus,
|
||||||
|
'partial' => $partial,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$this->fields = $result['fields'];
|
||||||
|
|
||||||
if (!empty($result['errors'])) {
|
if (!empty($result['errors'])) {
|
||||||
throw new ArcanistDifferentialCommitMessageParserException(
|
throw new ArcanistDifferentialCommitMessageParserException(
|
||||||
$result['errors']);
|
$result['errors']);
|
||||||
}
|
}
|
||||||
$this->fields = $result['fields'];
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFieldValue($key) {
|
public function getFieldValue($key) {
|
||||||
|
|
|
@ -1276,18 +1276,32 @@ EOTEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
$template_is_default = false;
|
$template_is_default = false;
|
||||||
|
$notes = array();
|
||||||
|
|
||||||
if (!$template) {
|
if (!$template) {
|
||||||
|
list($fields, $notes) = $this->getDefaultCreateFields();
|
||||||
|
if (!$fields) {
|
||||||
|
$template_is_default = true;
|
||||||
|
}
|
||||||
|
|
||||||
$template = $conduit->callMethodSynchronous(
|
$template = $conduit->callMethodSynchronous(
|
||||||
'differential.getcommitmessage',
|
'differential.getcommitmessage',
|
||||||
array(
|
array(
|
||||||
'revision_id' => null,
|
'revision_id' => null,
|
||||||
'edit' => true,
|
'edit' => 'create',
|
||||||
|
'fields' => $fields,
|
||||||
));
|
));
|
||||||
$template_is_default = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$issues = array('Describe this revision.');
|
$issues = array(
|
||||||
|
'Describe this revision.',
|
||||||
|
'',
|
||||||
|
'If you intended to update a existing revision, use ',
|
||||||
|
'`arc diff --update <revision>`.',
|
||||||
|
);
|
||||||
|
if ($notes) {
|
||||||
|
$issues = array_merge($issues, array(''), $notes);
|
||||||
|
}
|
||||||
|
|
||||||
$done = false;
|
$done = false;
|
||||||
while (!$done) {
|
while (!$done) {
|
||||||
|
@ -1312,7 +1326,6 @@ EOTEXT
|
||||||
$where = $this->getReadableScratchFilePath('create-message');
|
$where = $this->getReadableScratchFilePath('create-message');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
$message = ArcanistDifferentialCommitMessage::newFromRawCorpus(
|
$message = ArcanistDifferentialCommitMessage::newFromRawCorpus(
|
||||||
$template);
|
$template);
|
||||||
$message->pullDataFromConduit($conduit);
|
$message->pullDataFromConduit($conduit);
|
||||||
|
@ -1338,11 +1351,11 @@ EOTEXT
|
||||||
$saved = "A copy was saved to '{$where}'.";
|
$saved = "A copy was saved to '{$where}'.";
|
||||||
}
|
}
|
||||||
throw new ArcanistUsageException(
|
throw new ArcanistUsageException(
|
||||||
'Message has unresolved errrors. {$saved}');
|
"Message has unresolved errrors. {$saved}");
|
||||||
}
|
}
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
if ($wrote) {
|
if ($wrote) {
|
||||||
echo phutil_console_wrap("(Commit messaged saved to '{$where}'.)");
|
echo phutil_console_wrap("(Commit messaged saved to '{$where}'.)\n");
|
||||||
}
|
}
|
||||||
throw $ex;
|
throw $ex;
|
||||||
}
|
}
|
||||||
|
@ -1474,22 +1487,7 @@ EOTEXT
|
||||||
$conduit = $this->getConduit();
|
$conduit = $this->getConduit();
|
||||||
$repository_api = $this->getRepositoryAPI();
|
$repository_api = $this->getRepositoryAPI();
|
||||||
|
|
||||||
$parser = new ArcanistDiffParser();
|
$commit_messages = $this->getLocalGitCommitMessages();
|
||||||
$commit_messages = $repository_api->getGitCommitLog();
|
|
||||||
|
|
||||||
if (!strlen($commit_messages)) {
|
|
||||||
if (!$repository_api->getHasCommits()) {
|
|
||||||
throw new ArcanistUsageException(
|
|
||||||
"This git repository doesn't have any commits yet. You need to ".
|
|
||||||
"commit something before you can diff against it.");
|
|
||||||
} else {
|
|
||||||
throw new ArcanistUsageException(
|
|
||||||
"The commit range doesn't include any commits. (Did you diff ".
|
|
||||||
"against the wrong commit?)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$commit_messages = $parser->parseDiff($commit_messages);
|
|
||||||
|
|
||||||
$problems = array();
|
$problems = array();
|
||||||
$parsed = array();
|
$parsed = array();
|
||||||
|
@ -1536,20 +1534,15 @@ EOTEXT
|
||||||
$title = phutil_utf8_shorten($title, 64);
|
$title = phutil_utf8_shorten($title, 64);
|
||||||
echo " {$hash} {$title}\n";
|
echo " {$hash} {$title}\n";
|
||||||
}
|
}
|
||||||
echo " none Edit a blank template.";
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
$choose = phutil_console_prompt('Use which commit message [none]?');
|
$choose = phutil_console_prompt('Use which commit message?');
|
||||||
if ($choose == 'none' || $choose == '') {
|
|
||||||
return $this->getCommitMessageFromUser();
|
|
||||||
} else {
|
|
||||||
foreach ($valid as $key => $message) {
|
foreach ($valid as $key => $message) {
|
||||||
if (!strncmp($hashes[$key], $choose, strlen($choose))) {
|
if (!strncmp($hashes[$key], $choose, strlen($choose))) {
|
||||||
$blessed = $valid[$key];
|
$blessed = $valid[$key];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} while (!$blessed);
|
} while (!$blessed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1580,6 +1573,76 @@ EOTEXT
|
||||||
return $blessed;
|
return $blessed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getLocalGitCommitMessages() {
|
||||||
|
$repository_api = $this->getRepositoryAPI();
|
||||||
|
$parser = new ArcanistDiffParser();
|
||||||
|
$commit_messages = $repository_api->getGitCommitLog();
|
||||||
|
|
||||||
|
if (!strlen($commit_messages)) {
|
||||||
|
if (!$repository_api->getHasCommits()) {
|
||||||
|
throw new ArcanistUsageException(
|
||||||
|
"This git repository doesn't have any commits yet. You need to ".
|
||||||
|
"commit something before you can diff against it.");
|
||||||
|
} else {
|
||||||
|
throw new ArcanistUsageException(
|
||||||
|
"The commit range doesn't include any commits. (Did you diff ".
|
||||||
|
"against the wrong commit?)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parser->parseDiff($commit_messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDefaultCreateFields() {
|
||||||
|
$empty = array(array(), array());
|
||||||
|
|
||||||
|
if (!$this->requiresRepositoryAPI()) {
|
||||||
|
return $empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
$repository_api = $this->getRepositoryAPI();
|
||||||
|
if ($repository_api instanceof ArcanistGitAPI) {
|
||||||
|
return $this->getGitCreateFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getGitCreateFields() {
|
||||||
|
$conduit = $this->getConduit();
|
||||||
|
$changes = $this->getLocalGitCommitMessages();
|
||||||
|
|
||||||
|
$commits = array();
|
||||||
|
foreach ($changes as $key => $change) {
|
||||||
|
$commits[$change->getCommitHash()] = $change->getMetadata('message');
|
||||||
|
}
|
||||||
|
|
||||||
|
$messages = array();
|
||||||
|
foreach ($commits as $hash => $text) {
|
||||||
|
$messages[$hash] = ArcanistDifferentialCommitMessage::newFromRawCorpus(
|
||||||
|
$text);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fields = array();
|
||||||
|
$notes = array();
|
||||||
|
foreach ($messages as $hash => $message) {
|
||||||
|
try {
|
||||||
|
$message->pullDataFromConduit($conduit, $partial = true);
|
||||||
|
$fields += $message->getFields();
|
||||||
|
} catch (ArcanistDifferentialCommitMessageParserException $ex) {
|
||||||
|
$fields += $message->getFields();
|
||||||
|
|
||||||
|
$frev = substr($hash, 0, 8);
|
||||||
|
$notes[] = "NOTE: commit {$frev} could not be completely parsed:";
|
||||||
|
foreach ($ex->getParserErrors() as $error) {
|
||||||
|
$notes[] = " - {$error}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array($fields, $notes);
|
||||||
|
}
|
||||||
|
|
||||||
private function getDefaultUpdateMessage() {
|
private function getDefaultUpdateMessage() {
|
||||||
if (!$this->requiresRepositoryAPI()) {
|
if (!$this->requiresRepositoryAPI()) {
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Reference in a new issue