mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-17 12:22:42 +01:00
Provide a new "hint" table for weird commits (rewritten, unreadable)
Summary: Ref T11522. This provides storage for tracking rewritten commits (new feature) and unreadable commits (existing feature, but really hacky). This doesn't do anything yet, just adds a table and a CLI tool for updating it. I'll document the tool once it works. You just pipe in some JSON, but I need to document the format. Test Plan: - Piped JSON for "none", "rewritten" and "unreadable" hints into `bin/repository hint`. - Examined the database to see that the table was written properly. - Tried to pipe bad JSON in, invalid hint types, etc. Got reasonable human-readable error messages. Reviewers: chad Reviewed By: chad Maniphest Tasks: T11522 Differential Revision: https://secure.phabricator.com/D16434
This commit is contained in:
parent
2201c65eb7
commit
8a4fbcd8c0
5 changed files with 306 additions and 0 deletions
8
resources/sql/autopatches/20160824.repohint.01.hint.sql
Normal file
8
resources/sql/autopatches/20160824.repohint.01.hint.sql
Normal file
|
@ -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};
|
|
@ -612,6 +612,7 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'DiffusionCommitHash' => 'Phobject',
|
||||
'DiffusionCommitHeraldField' => 'HeraldField',
|
||||
'DiffusionCommitHeraldFieldGroup' => 'HeraldFieldGroup',
|
||||
'DiffusionCommitHintQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'DiffusionCommitHookEngine' => 'Phobject',
|
||||
'DiffusionCommitHookRejectException' => 'Exception',
|
||||
'DiffusionCommitMergeHeraldField' => 'DiffusionCommitHeraldField',
|
||||
|
@ -8348,6 +8352,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
|
||||
'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
|
||||
'PhabricatorRepositoryCommitHeraldWorker' => 'PhabricatorRepositoryCommitParserWorker',
|
||||
'PhabricatorRepositoryCommitHint' => array(
|
||||
'PhabricatorRepositoryDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
),
|
||||
'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
|
||||
'PhabricatorRepositoryCommitOwnersWorker' => 'PhabricatorRepositoryCommitParserWorker',
|
||||
'PhabricatorRepositoryCommitPHIDType' => 'PhabricatorPHIDType',
|
||||
|
@ -8372,6 +8380,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRepositoryManagementCacheWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementClusterizeWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementHintWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementImportingWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementListPathsWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
'PhabricatorRepositoryManagementListWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
||||
}
|
|
@ -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']));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue