From 2fa18d80f8e310c28167d8d6f51c643afa28a8c1 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 28 Feb 2012 17:00:35 -0800 Subject: [PATCH] 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 --- .gitignore | 1 + .../ArcanistDifferentialCommitMessage.php | 16 ++- src/workflow/diff/ArcanistDiffWorkflow.php | 127 +++++++++++++----- 3 files changed, 108 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index 6707f606..8e146282 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /src/.phutil_module_cache /docs/ /.divinercache/ +/.arc/ diff --git a/src/differential/commitmessage/ArcanistDifferentialCommitMessage.php b/src/differential/commitmessage/ArcanistDifferentialCommitMessage.php index 1be8f675..95733663 100644 --- a/src/differential/commitmessage/ArcanistDifferentialCommitMessage.php +++ b/src/differential/commitmessage/ArcanistDifferentialCommitMessage.php @@ -25,7 +25,7 @@ final class ArcanistDifferentialCommitMessage { private $rawCorpus; private $revisionID; - private $fields; + private $fields = array(); private $gitSVNBaseRevision; private $gitSVNBasePath; @@ -78,17 +78,25 @@ final class ArcanistDifferentialCommitMessage { return $this->revisionID; } - public function pullDataFromConduit(ConduitClient $conduit) { + public function pullDataFromConduit( + ConduitClient $conduit, + $partial = false) { + $result = $conduit->callMethodSynchronous( 'differential.parsecommitmessage', array( - 'corpus' => $this->rawCorpus, + 'corpus' => $this->rawCorpus, + 'partial' => $partial, )); + + $this->fields = $result['fields']; + if (!empty($result['errors'])) { throw new ArcanistDifferentialCommitMessageParserException( $result['errors']); } - $this->fields = $result['fields']; + + return $this; } public function getFieldValue($key) { diff --git a/src/workflow/diff/ArcanistDiffWorkflow.php b/src/workflow/diff/ArcanistDiffWorkflow.php index 7c596b63..07cbcf1e 100644 --- a/src/workflow/diff/ArcanistDiffWorkflow.php +++ b/src/workflow/diff/ArcanistDiffWorkflow.php @@ -1276,18 +1276,32 @@ EOTEXT } $template_is_default = false; + $notes = array(); if (!$template) { + list($fields, $notes) = $this->getDefaultCreateFields(); + if (!$fields) { + $template_is_default = true; + } + $template = $conduit->callMethodSynchronous( 'differential.getcommitmessage', array( '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 `.', + ); + if ($notes) { + $issues = array_merge($issues, array(''), $notes); + } $done = false; while (!$done) { @@ -1312,7 +1326,6 @@ EOTEXT $where = $this->getReadableScratchFilePath('create-message'); try { - $message = ArcanistDifferentialCommitMessage::newFromRawCorpus( $template); $message->pullDataFromConduit($conduit); @@ -1338,11 +1351,11 @@ EOTEXT $saved = "A copy was saved to '{$where}'."; } throw new ArcanistUsageException( - 'Message has unresolved errrors. {$saved}'); + "Message has unresolved errrors. {$saved}"); } } catch (Exception $ex) { if ($wrote) { - echo phutil_console_wrap("(Commit messaged saved to '{$where}'.)"); + echo phutil_console_wrap("(Commit messaged saved to '{$where}'.)\n"); } throw $ex; } @@ -1474,22 +1487,7 @@ EOTEXT $conduit = $this->getConduit(); $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?)"); - } - } - - $commit_messages = $parser->parseDiff($commit_messages); + $commit_messages = $this->getLocalGitCommitMessages(); $problems = array(); $parsed = array(); @@ -1536,18 +1534,13 @@ EOTEXT $title = phutil_utf8_shorten($title, 64); echo " {$hash} {$title}\n"; } - echo " none Edit a blank template."; do { - $choose = phutil_console_prompt('Use which commit message [none]?'); - if ($choose == 'none' || $choose == '') { - return $this->getCommitMessageFromUser(); - } else { - foreach ($valid as $key => $message) { - if (!strncmp($hashes[$key], $choose, strlen($choose))) { - $blessed = $valid[$key]; - break; - } + $choose = phutil_console_prompt('Use which commit message?'); + foreach ($valid as $key => $message) { + if (!strncmp($hashes[$key], $choose, strlen($choose))) { + $blessed = $valid[$key]; + break; } } } while (!$blessed); @@ -1580,6 +1573,76 @@ EOTEXT 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() { if (!$this->requiresRepositoryAPI()) { return null;