Page MenuHomePhabricator

D16434.diff
No OneTemporary

D16434.diff

diff --git a/resources/sql/autopatches/20160824.repohint.01.hint.sql b/resources/sql/autopatches/20160824.repohint.01.hint.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20160824.repohint.01.hint.sql
@@ -0,0 +1,8 @@
+CREATE TABLE {$NAMESPACE}_repository.repository_commithint (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ repositoryPHID VARBINARY(64) NOT NULL,
+ oldCommitIdentifier VARCHAR(40) NOT NULL COLLATE {$COLLATE_TEXT},
+ newCommitIdentifier VARCHAR(40) COLLATE {$COLLATE_TEXT},
+ hintType VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
+ UNIQUE KEY `key_old` (repositoryPHID, oldCommitIdentifier)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
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
@@ -612,6 +612,7 @@
'DiffusionCommitHash' => 'applications/diffusion/data/DiffusionCommitHash.php',
'DiffusionCommitHeraldField' => 'applications/diffusion/herald/DiffusionCommitHeraldField.php',
'DiffusionCommitHeraldFieldGroup' => 'applications/diffusion/herald/DiffusionCommitHeraldFieldGroup.php',
+ 'DiffusionCommitHintQuery' => 'applications/diffusion/query/DiffusionCommitHintQuery.php',
'DiffusionCommitHookEngine' => 'applications/diffusion/engine/DiffusionCommitHookEngine.php',
'DiffusionCommitHookRejectException' => 'applications/diffusion/exception/DiffusionCommitHookRejectException.php',
'DiffusionCommitMergeHeraldField' => 'applications/diffusion/herald/DiffusionCommitMergeHeraldField.php',
@@ -3383,6 +3384,7 @@
'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php',
'PhabricatorRepositoryCommitData' => 'applications/repository/storage/PhabricatorRepositoryCommitData.php',
'PhabricatorRepositoryCommitHeraldWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitHeraldWorker.php',
+ 'PhabricatorRepositoryCommitHint' => 'applications/repository/storage/PhabricatorRepositoryCommitHint.php',
'PhabricatorRepositoryCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php',
'PhabricatorRepositoryCommitOwnersWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitOwnersWorker.php',
'PhabricatorRepositoryCommitPHIDType' => 'applications/repository/phid/PhabricatorRepositoryCommitPHIDType.php',
@@ -3403,6 +3405,7 @@
'PhabricatorRepositoryManagementCacheWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementCacheWorkflow.php',
'PhabricatorRepositoryManagementClusterizeWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementClusterizeWorkflow.php',
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDiscoverWorkflow.php',
+ 'PhabricatorRepositoryManagementHintWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementHintWorkflow.php',
'PhabricatorRepositoryManagementImportingWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementImportingWorkflow.php',
'PhabricatorRepositoryManagementListPathsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListPathsWorkflow.php',
'PhabricatorRepositoryManagementListWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListWorkflow.php',
@@ -5104,6 +5107,7 @@
'DiffusionCommitHash' => 'Phobject',
'DiffusionCommitHeraldField' => 'HeraldField',
'DiffusionCommitHeraldFieldGroup' => 'HeraldFieldGroup',
+ 'DiffusionCommitHintQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'DiffusionCommitHookEngine' => 'Phobject',
'DiffusionCommitHookRejectException' => 'Exception',
'DiffusionCommitMergeHeraldField' => 'DiffusionCommitHeraldField',
@@ -8348,6 +8352,10 @@
'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryCommitHeraldWorker' => 'PhabricatorRepositoryCommitParserWorker',
+ 'PhabricatorRepositoryCommitHint' => array(
+ 'PhabricatorRepositoryDAO',
+ 'PhabricatorPolicyInterface',
+ ),
'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitOwnersWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitPHIDType' => 'PhabricatorPHIDType',
@@ -8372,6 +8380,7 @@
'PhabricatorRepositoryManagementCacheWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementClusterizeWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
+ 'PhabricatorRepositoryManagementHintWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementImportingWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementListPathsWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementListWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
diff --git a/src/applications/diffusion/query/DiffusionCommitHintQuery.php b/src/applications/diffusion/query/DiffusionCommitHintQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/query/DiffusionCommitHintQuery.php
@@ -0,0 +1,64 @@
+<?php
+
+final class DiffusionCommitHintQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $ids;
+ private $repositoryPHIDs;
+ private $oldCommitIdentifiers;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
+
+ public function withRepositoryPHIDs(array $phids) {
+ $this->repositoryPHIDs = $phids;
+ return $this;
+ }
+
+ public function withOldCommitIdentifiers(array $identifiers) {
+ $this->oldCommitIdentifiers = $identifiers;
+ return $this;
+ }
+
+ public function newResultObject() {
+ return new PhabricatorRepositoryCommitHint();
+ }
+
+ protected function loadPage() {
+ return $this->loadStandardPage($this->newResultObject());
+ }
+
+ protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
+ $where = parent::buildWhereClauseParts($conn);
+
+ if ($this->ids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'id IN (%Ld)',
+ $this->ids);
+ }
+
+ if ($this->repositoryPHIDs !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'reositoryPHID IN (%Ls)',
+ $this->repositoryPHIDs);
+ }
+
+ if ($this->oldCommitIdentifiers !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'oldCommitIdentifier IN (%Ls)',
+ $this->oldCommitIdentifiers);
+ }
+
+ return $where;
+ }
+
+ public function getQueryApplicationClass() {
+ return 'PhabricatorDiffusionApplication';
+ }
+
+}
diff --git a/src/applications/repository/management/PhabricatorRepositoryManagementHintWorkflow.php b/src/applications/repository/management/PhabricatorRepositoryManagementHintWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/management/PhabricatorRepositoryManagementHintWorkflow.php
@@ -0,0 +1,97 @@
+<?php
+
+final class PhabricatorRepositoryManagementHintWorkflow
+ extends PhabricatorRepositoryManagementWorkflow {
+
+ protected function didConstruct() {
+ $this
+ ->setName('hint')
+ ->setExamples('**hint** [options] ...')
+ ->setSynopsis(
+ pht(
+ 'Write hints about unusual (rewritten or unreadable) commits.'))
+ ->setArguments(array());
+ }
+
+ public function execute(PhutilArgumentParser $args) {
+ $viewer = $this->getViewer();
+
+ echo tsprintf(
+ "%s\n",
+ pht('Reading list of hints from stdin...'));
+
+ $hints = file_get_contents('php://stdin');
+ if ($hints === false) {
+ throw new PhutilArgumentUsageException(pht('Failed to read stdin.'));
+ }
+
+ try {
+ $hints = phutil_json_decode($hints);
+ } catch (Exception $ex) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Expected a list of hints in JSON format: %s',
+ $ex->getMessage()));
+ }
+
+ $repositories = array();
+ foreach ($hints as $idx => $hint) {
+ if (!is_array($hint)) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Each item in the list of hints should be a JSON object, but '.
+ 'the item at index "%s" is not.',
+ $idx));
+ }
+
+ try {
+ PhutilTypeSpec::checkMap(
+ $hint,
+ array(
+ 'repository' => 'string|int',
+ 'old' => 'string',
+ 'new' => 'optional string|null',
+ 'hint' => 'string',
+ ));
+ } catch (Exception $ex) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Unexpected hint format at index "%s": %s',
+ $idx,
+ $ex->getMessage()));
+ }
+
+ $repository_identifier = $hint['repository'];
+ $repository = idx($repositories, $repository_identifier);
+ if (!$repository) {
+ $repository = id(new PhabricatorRepositoryQuery())
+ ->setViewer($viewer)
+ ->withIdentifiers(array($repository_identifier))
+ ->executeOne();
+ if (!$repository) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Repository identifier "%s" (in hint at index "%s") does not '.
+ 'identify a valid repository.',
+ $repository_identifier,
+ $idx));
+ }
+
+ $repositories[$repository_identifier] = $repository;
+ }
+
+ PhabricatorRepositoryCommitHint::updateHint(
+ $repository->getPHID(),
+ $hint['old'],
+ idx($hint, 'new'),
+ $hint['hint']);
+
+ echo tsprintf(
+ "%s\n",
+ pht(
+ 'Updated hint for "%s".',
+ $hint['old']));
+ }
+ }
+
+}
diff --git a/src/applications/repository/storage/PhabricatorRepositoryCommitHint.php b/src/applications/repository/storage/PhabricatorRepositoryCommitHint.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/storage/PhabricatorRepositoryCommitHint.php
@@ -0,0 +1,128 @@
+<?php
+
+final class PhabricatorRepositoryCommitHint
+ extends PhabricatorRepositoryDAO
+ implements PhabricatorPolicyInterface {
+
+ protected $repositoryPHID;
+ protected $oldCommitIdentifier;
+ protected $newCommitIdentifier;
+ protected $hintType;
+
+ const HINT_NONE = 'none';
+ const HINT_REWRITTEN = 'rewritten';
+ const HINT_UNREADABLE = 'unreadable';
+
+ protected function getConfiguration() {
+ return array(
+ self::CONFIG_TIMESTAMPS => false,
+ self::CONFIG_COLUMN_SCHEMA => array(
+ 'oldCommitIdentifier' => 'text40',
+ 'newCommitIdentifier' => 'text40?',
+ 'hintType' => 'text32',
+ ),
+ self::CONFIG_KEY_SCHEMA => array(
+ 'key_old' => array(
+ 'columns' => array('repositoryPHID', 'oldCommitIdentifier'),
+ 'unique' => true,
+ ),
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ public static function getAllHintTypes() {
+ return array(
+ self::HINT_NONE,
+ self::HINT_REWRITTEN,
+ self::HINT_UNREADABLE,
+ );
+ }
+
+ public static function updateHint($repository_phid, $old, $new, $type) {
+ switch ($type) {
+ case self::HINT_NONE:
+ break;
+ case self::HINT_REWRITTEN:
+ if (!$new) {
+ throw new Exception(
+ pht(
+ 'When hinting a commit ("%s") as rewritten, you must provide '.
+ 'the commit it was rewritten into.',
+ $old));
+ }
+ break;
+ case self::HINT_UNREADABLE:
+ if ($new) {
+ throw new Exception(
+ pht(
+ 'When hinting a commit ("%s") as unreadable, you must not '.
+ 'provide a new commit ("%s").',
+ $old,
+ $new));
+ }
+ break;
+ default:
+ $all_types = self::getAllHintTypes();
+ throw new Exception(
+ pht(
+ 'Hint type ("%s") for commit ("%s") is not valid. Valid hints '.
+ 'are: %s.',
+ $type,
+ $old,
+ implode(', ', $all_types)));
+ }
+
+ $table = new self();
+ $table_name = $table->getTableName();
+ $conn = $table->establishConnection('w');
+
+ if ($type == self::HINT_NONE) {
+ queryfx(
+ $conn,
+ 'DELETE FROM %T WHERE repositoryPHID = %s AND oldCommitIdentifier = %s',
+ $table_name,
+ $repository_phid,
+ $old);
+ } else {
+ queryfx(
+ $conn,
+ 'INSERT INTO %T
+ (repositoryPHID, oldCommitIdentifier, newCommitIdentifier, hintType)
+ VALUES (%s, %s, %ns, %s)
+ ON DUPLICATE KEY UPDATE
+ newCommitIdentifier = VALUES(newCommitIdentifier),
+ hintType = VALUES(hintType)',
+ $table_name,
+ $repository_phid,
+ $old,
+ $new,
+ $type);
+ }
+ }
+
+
+/* -( PhabricatorPolicyInterface )----------------------------------------- */
+
+
+ public function getCapabilities() {
+ return array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ );
+ }
+
+ public function getPolicy($capability) {
+ switch ($capability) {
+ case PhabricatorPolicyCapability::CAN_VIEW:
+ return PhabricatorPolicies::getMostOpenPolicy();
+ }
+ }
+
+ public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
+ return false;
+ }
+
+ public function describeAutomaticCapability($capability) {
+ return null;
+ }
+
+}

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 13, 12:13 PM (5 d, 5 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6753483
Default Alt Text
D16434.diff (13 KB)

Event Timeline