Page MenuHomePhabricator

D9130.id25499.diff
No OneTemporary

D9130.id25499.diff

diff --git a/resources/sql/autopatches/20140515.factlint.1.sql b/resources/sql/autopatches/20140515.factlint.1.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20140515.factlint.1.sql
@@ -0,0 +1,8 @@
+ALTER TABLE {$NAMESPACE}_fact.fact_raw
+ADD COLUMN `stringA` VARCHAR(2048) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL;
+
+ALTER TABLE {$NAMESPACE}_fact.fact_aggregate
+ADD COLUMN `stringA` VARCHAR(2048) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL;
+
+ALTER TABLE {$NAMESPACE}_repository.repository_branch
+ADD COLUMN `phid` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL;
diff --git a/resources/sql/autopatches/20140515.factlint.2.php b/resources/sql/autopatches/20140515.factlint.2.php
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20140515.factlint.2.php
@@ -0,0 +1,15 @@
+<?php
+
+$branches = id(new PhabricatorRepositoryBranch())->loadAll();
+
+foreach ($branches as $branch) {
+ if ($branch->getPHID() == null) {
+ $id = $branch->getID();
+ echo "Generating PHID for branch ID {$id}...\n";
+
+ $branch->setPHID(
+ PhabricatorPHID::generateNewPHID(
+ PhabricatorRepositoryPHIDTypeBranch::TYPECONST));
+ $branch->save();
+ }
+}
diff --git a/resources/sql/autopatches/20140515.factlint.3.sql b/resources/sql/autopatches/20140515.factlint.3.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20140515.factlint.3.sql
@@ -0,0 +1,5 @@
+ALTER TABLE {$NAMESPACE}_repository.repository_branch
+ADD UNIQUE KEY `phid` (`phid`);
+
+ALTER TABLE {$NAMESPACE}_repository.repository_branch
+MODIFY `phid` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL;
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
@@ -1567,6 +1567,7 @@
'PhabricatorFactEngine' => 'applications/fact/engine/PhabricatorFactEngine.php',
'PhabricatorFactHomeController' => 'applications/fact/controller/PhabricatorFactHomeController.php',
'PhabricatorFactLastUpdatedEngine' => 'applications/fact/engine/PhabricatorFactLastUpdatedEngine.php',
+ 'PhabricatorFactLintEngine' => 'applications/diffusion/fact/PhabricatorFactLintEngine.php',
'PhabricatorFactManagementAnalyzeWorkflow' => 'applications/fact/management/PhabricatorFactManagementAnalyzeWorkflow.php',
'PhabricatorFactManagementCursorsWorkflow' => 'applications/fact/management/PhabricatorFactManagementCursorsWorkflow.php',
'PhabricatorFactManagementDestroyWorkflow' => 'applications/fact/management/PhabricatorFactManagementDestroyWorkflow.php',
@@ -2133,6 +2134,7 @@
'PhabricatorRepositoryMirrorEngine' => 'applications/repository/engine/PhabricatorRepositoryMirrorEngine.php',
'PhabricatorRepositoryMirrorPHIDType' => 'applications/repository/phid/PhabricatorRepositoryMirrorPHIDType.php',
'PhabricatorRepositoryMirrorQuery' => 'applications/repository/query/PhabricatorRepositoryMirrorQuery.php',
+ 'PhabricatorRepositoryPHIDTypeBranch' => 'applications/repository/phid/PhabricatorRepositoryPHIDTypeBranch.php',
'PhabricatorRepositoryParsedChange' => 'applications/repository/data/PhabricatorRepositoryParsedChange.php',
'PhabricatorRepositoryPullEngine' => 'applications/repository/engine/PhabricatorRepositoryPullEngine.php',
'PhabricatorRepositoryPullLocalDaemon' => 'applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php',
@@ -4524,6 +4526,7 @@
'PhabricatorFactDaemon' => 'PhabricatorDaemon',
'PhabricatorFactHomeController' => 'PhabricatorFactController',
'PhabricatorFactLastUpdatedEngine' => 'PhabricatorFactEngine',
+ 'PhabricatorFactLintEngine' => 'PhabricatorFactEngine',
'PhabricatorFactManagementAnalyzeWorkflow' => 'PhabricatorFactManagementWorkflow',
'PhabricatorFactManagementCursorsWorkflow' => 'PhabricatorFactManagementWorkflow',
'PhabricatorFactManagementDestroyWorkflow' => 'PhabricatorFactManagementWorkflow',
@@ -5136,6 +5139,7 @@
'PhabricatorRepositoryMirrorEngine' => 'PhabricatorRepositoryEngine',
'PhabricatorRepositoryMirrorPHIDType' => 'PhabricatorPHIDType',
'PhabricatorRepositoryMirrorQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'PhabricatorRepositoryPHIDTypeBranch' => 'PhabricatorPHIDType',
'PhabricatorRepositoryParsedChange' => 'Phobject',
'PhabricatorRepositoryPullEngine' => 'PhabricatorRepositoryEngine',
'PhabricatorRepositoryPullLocalDaemon' => 'PhabricatorDaemon',
diff --git a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php
--- a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php
+++ b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php
@@ -29,6 +29,7 @@
public function getFactObjectsForAnalysis() {
return array(
new PhabricatorRepositoryCommit(),
+ new PhabricatorRepositoryBranch(),
);
}
diff --git a/src/applications/diffusion/fact/PhabricatorFactLintEngine.php b/src/applications/diffusion/fact/PhabricatorFactLintEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/fact/PhabricatorFactLintEngine.php
@@ -0,0 +1,145 @@
+<?php
+
+/**
+ * Fact engine which reports lint information.
+ */
+final class PhabricatorFactLintEngine extends PhabricatorFactEngine {
+
+ const TYPE_LINT_COUNT_BY_PATH = 'L:PATH';
+
+ public function getFactSpecs(array $fact_types) {
+ $results = array();
+
+ foreach ($fact_types as $type) {
+ if ($type == self::TYPE_LINT_COUNT_BY_PATH) {
+ $name = 'Lint Messages by Path';
+
+ $results[] = id(new PhabricatorFactSimpleSpec($type))
+ ->setName($name)
+ ->setUnit(PhabricatorFactSimpleSpec::UNIT_COUNT);
+
+ }
+ }
+
+ return $results;
+ }
+
+ public function shouldComputeRawFactsForObject(PhabricatorLiskDAO $object) {
+ return ($object instanceof PhabricatorRepositoryBranch);
+ }
+
+ public function computeRawFactsForObject(
+ PhabricatorRepositoryBranch $branch) {
+
+ $facts = array();
+
+ $phid = $branch->getPHID();
+
+ $conn = $branch->establishConnection('r');
+
+ // Emit lint message counts by file.
+ $message_count_by_path = queryfx_all(
+ $conn,
+ 'SELECT COUNT(*) AS n, path FROM %T WHERE branchID = %d GROUP BY path',
+ PhabricatorRepository::TABLE_LINTMESSAGE,
+ $branch->getID());
+
+ $existing_facts_by_path = id(new PhabricatorFactAggregate())->loadAllWhere(
+ 'objectPHID = %s AND factType = %s',
+ $phid,
+ self::TYPE_LINT_COUNT_BY_PATH);
+ $existing_facts_by_path = mgroup($existing_facts_by_path, 'getStringA');
+
+ $relative_change = array();
+
+ foreach ($message_count_by_path as $message) {
+ $existing = idx($existing_facts_by_path, $message['path']);
+
+ if ($existing === null) {
+ $existing_count = 0;
+ } else {
+ $existing = reset($existing);
+ $existing_count = $existing->getValueX();
+ }
+
+ $relative_change[$message['path']] = $message['n'] - $existing_count;
+
+ $facts[] = id(new PhabricatorFactRaw())
+ ->setFactType(self::TYPE_LINT_COUNT_BY_PATH)
+ ->setObjectPHID($phid)
+ ->setStringA($message['path'])
+ ->setValueX($message['n'] - $existing_count)
+ ->setEpoch($branch->getDateModified());
+ }
+
+ // Emit lint message counts by folder.
+ $folder_paths = array();
+
+ foreach ($message_count_by_path as $message) {
+ $current = $message['path'];
+ $dirnames = array();
+ while ($current !== '/') {
+ $current = dirname($current);
+ $dirnames[] = $current;
+ }
+
+ foreach ($dirnames as $d) {
+ if (!array_key_exists($d, $folder_paths)) {
+ $folder_paths[$d] = array();
+ }
+
+ $folder_paths[$d][$message['path']] =
+ $relative_change[$message['path']];
+ }
+ }
+
+ $folder_facts = array();
+ foreach ($folder_paths as $path => $details) {
+ $sum = 0;
+ foreach ($details as $source_path => $value) {
+ $sum += $value;
+ }
+
+ $facts[] = id(new PhabricatorFactRaw())
+ ->setFactType(self::TYPE_LINT_COUNT_BY_PATH)
+ ->setObjectPHID($phid)
+ ->setStringA($path)
+ ->setValueX($sum)
+ ->setEpoch($branch->getDateModified());
+ }
+
+ return $facts;
+ }
+
+ public function shouldComputeAggregateFacts() {
+ return true;
+ }
+
+ public function computeAggregateFacts() {
+ $table = new PhabricatorFactRaw();
+ $table_name = $table->getTableName();
+ $conn = $table->establishConnection('r');
+
+ $counts = queryfx_all(
+ $conn,
+ 'SELECT SUM(valueX) AS n, objectPHID, stringA
+ FROM %T
+ WHERE factType = %s
+ GROUP BY objectPHID, stringA',
+ $table_name,
+ self::TYPE_LINT_COUNT_BY_PATH);
+
+ $facts = array();
+ foreach ($counts as $count) {
+ $facts[] = id(new PhabricatorFactAggregate())
+ ->setFactType(self::TYPE_LINT_COUNT_BY_PATH)
+ ->setObjectPHID($count['objectPHID'])
+ ->setStringA($count['stringA'])
+ ->setValueX($count['n']);
+ }
+
+ return $facts;
+ }
+
+
+}
diff --git a/src/applications/fact/controller/PhabricatorFactChartController.php b/src/applications/fact/controller/PhabricatorFactChartController.php
--- a/src/applications/fact/controller/PhabricatorFactChartController.php
+++ b/src/applications/fact/controller/PhabricatorFactChartController.php
@@ -11,17 +11,24 @@
$table_name = $table->getTableName();
$series = $request->getStr('y1');
+ $filter_a = $request->getStr('sa');
$specs = PhabricatorFactSpec::newSpecsForFactTypes(
PhabricatorFactEngine::loadAllEngines(),
array($series));
$spec = idx($specs, $series);
+ $filter = '';
+ if ($filter_a !== '') {
+ $filter .= qsprintf($conn_r, 'AND stringA = %s', $filter_a);
+ }
+
$data = queryfx_all(
$conn_r,
- 'SELECT valueX, epoch FROM %T WHERE factType = %s ORDER BY epoch ASC',
+ 'SELECT valueX, epoch FROM %T WHERE factType = %s %Q ORDER BY epoch ASC',
$table_name,
- $series);
+ $series,
+ $filter);
$points = array();
$sum = 0;
@@ -76,8 +83,13 @@
'colors' => array('#0000ff'),
));
+ $filter_name = '';
+ if ($filter_a !== '') {
+ $filter_name = pht(' (filtered by %s)', $filter_a);
+ }
+
$panel = new AphrontPanelView();
- $panel->setHeader('Count of '.$spec->getName());
+ $panel->setHeader('Count of '.$spec->getName().$filter_name);
$panel->appendChild($chart);
$crumbs = $this->buildApplicationCrumbs();
diff --git a/src/applications/fact/controller/PhabricatorFactHomeController.php b/src/applications/fact/controller/PhabricatorFactHomeController.php
--- a/src/applications/fact/controller/PhabricatorFactHomeController.php
+++ b/src/applications/fact/controller/PhabricatorFactHomeController.php
@@ -13,6 +13,7 @@
if ($request->isFormPost()) {
$uri = new PhutilURI('/fact/chart/');
$uri->setQueryParam('y1', $request->getStr('y1'));
+ $uri->setQueryParam('sa', $request->getStr('sa'));
return id(new AphrontRedirectResponse())->setURI($uri);
}
@@ -113,6 +114,15 @@
->setLabel('Y-Axis')
->setName('y1')
->setOptions($options))
+ // TODO: Make this appear / disappear based on whether
+ // the Y-Axis uses it?
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setLabel('Optional String A')
+ ->setName('sa')
+ ->setCaption(pht(
+ 'This is an optional filtering '.
+ 'string that some facts use.')))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Plot Chart'));
diff --git a/src/applications/fact/daemon/PhabricatorFactDaemon.php b/src/applications/fact/daemon/PhabricatorFactDaemon.php
--- a/src/applications/fact/daemon/PhabricatorFactDaemon.php
+++ b/src/applications/fact/daemon/PhabricatorFactDaemon.php
@@ -139,10 +139,11 @@
foreach ($facts as $fact) {
$sql[] = qsprintf(
$conn,
- '(%s, %s, %s, %d, %d, %d)',
+ '(%s, %s, %s, %s, %d, %d, %d)',
$fact->getFactType(),
$fact->getObjectPHID(),
$fact->getObjectA(),
+ $fact->getStringA(),
$fact->getValueX(),
$fact->getValueY(),
$fact->getEpoch());
@@ -151,18 +152,36 @@
$table->openTransaction();
- queryfx(
- $conn,
- 'DELETE FROM %T WHERE objectPHID IN (%Ls)',
- $table_name,
- $phids);
+ // TODO: I need feedback here!
+ // FIXME: I need feedback here!
+
+ // What's the best way to specify that an updated object
+ // should create a new Fact and not remove the existing
+ // raw data? In the lint case we're detecting an
+ // updated branch but we want to keep the old data.
+
+ // HACK
+ $phids_delete = array();
+ foreach ($phids as $phid) {
+ if (substr_count($phid, 'BRNH') === 0) {
+ $phids_delete[] = $phid;
+ }
+ }
+
+ if (count($phids_delete) > 0) {
+ queryfx(
+ $conn,
+ 'DELETE FROM %T WHERE objectPHID IN (%Ls)',
+ $table_name,
+ $phids_delete);
+ }
if ($sql) {
foreach (array_chunk($sql, 256) as $chunk) {
queryfx(
$conn,
'INSERT INTO %T
- (factType, objectPHID, objectA, valueX, valueY, epoch)
+ (factType, objectPHID, objectA, stringA, valueX, valueY, epoch)
VALUES %Q',
$table_name,
implode(', ', $chunk));
@@ -185,16 +204,17 @@
foreach ($facts as $fact) {
$sql[] = qsprintf(
$conn,
- '(%s, %s, %d)',
+ '(%s, %s, %s, %d)',
$fact->getFactType(),
$fact->getObjectPHID(),
+ $fact->getStringA(),
$fact->getValueX());
}
foreach (array_chunk($sql, 256) as $chunk) {
queryfx(
$conn,
- 'INSERT INTO %T (factType, objectPHID, valueX) VALUES %Q
+ 'INSERT INTO %T (factType, objectPHID, stringA, valueX) VALUES %Q
ON DUPLICATE KEY UPDATE valueX = VALUES(valueX)',
$table_name,
implode(', ', $chunk));
diff --git a/src/applications/fact/storage/PhabricatorFactAggregate.php b/src/applications/fact/storage/PhabricatorFactAggregate.php
--- a/src/applications/fact/storage/PhabricatorFactAggregate.php
+++ b/src/applications/fact/storage/PhabricatorFactAggregate.php
@@ -4,6 +4,7 @@
protected $factType;
protected $objectPHID;
+ protected $stringA;
protected $valueX;
public function getConfiguration() {
diff --git a/src/applications/fact/storage/PhabricatorFactRaw.php b/src/applications/fact/storage/PhabricatorFactRaw.php
--- a/src/applications/fact/storage/PhabricatorFactRaw.php
+++ b/src/applications/fact/storage/PhabricatorFactRaw.php
@@ -8,6 +8,7 @@
protected $factType;
protected $objectPHID;
protected $objectA;
+ protected $stringA;
protected $valueX;
protected $valueY;
protected $epoch;
diff --git a/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeBranch.php b/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeBranch.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/phid/PhabricatorRepositoryPHIDTypeBranch.php
@@ -0,0 +1,36 @@
+<?php
+
+final class PhabricatorRepositoryPHIDTypeBranch extends PhabricatorPHIDType {
+
+ const TYPECONST = 'BRNH';
+
+ public function getTypeName() {
+ return pht('Branch');
+ }
+
+ public function getPHIDTypeApplicationClass() {
+ return 'PhabricatorApplicationDiffusion';
+ }
+
+ public function newObject() {
+ return new PhabricatorRepositoryBranch();
+ }
+
+ protected function buildQueryForObjects(
+ PhabricatorObjectQuery $query,
+ array $phids) {
+
+ // TODO?
+ return null;
+ }
+
+ public function loadHandles(
+ PhabricatorHandleQuery $query,
+ array $handles,
+ array $objects) {
+
+ // TODO?
+ return array();
+ }
+
+}
diff --git a/src/applications/repository/storage/PhabricatorRepositoryBranch.php b/src/applications/repository/storage/PhabricatorRepositoryBranch.php
--- a/src/applications/repository/storage/PhabricatorRepositoryBranch.php
+++ b/src/applications/repository/storage/PhabricatorRepositoryBranch.php
@@ -2,12 +2,14 @@
final class PhabricatorRepositoryBranch extends PhabricatorRepositoryDAO {
+ protected $phid;
protected $repositoryID;
protected $name;
protected $lintCommit;
public function getConfiguration() {
return array(
+ self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
'name' => 'text128',
'lintCommit' => 'text40?',
@@ -40,4 +42,8 @@
->save();
}
+ public function generatePHID() {
+ return PhabricatorPHID::generateNewPHID(
+ PhabricatorRepositoryPHIDTypeBranch::TYPECONST);
+ }
}

File Metadata

Mime Type
text/plain
Expires
Thu, Jun 27, 11:52 AM (1 d, 20 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6275665
Default Alt Text
D9130.id25499.diff (16 KB)

Event Timeline