1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-14 09:36:14 +01:00

(stable) Promote 2018 Week 7

This commit is contained in:
epriestley 2018-02-16 14:00:10 -08:00
commit a6100a4ce7
149 changed files with 3494 additions and 1459 deletions

View file

@ -10,10 +10,10 @@ return array(
'conpherence.pkg.css' => 'e68cf1fa',
'conpherence.pkg.js' => '15191c65',
'core.pkg.css' => 'e4f098a5',
'core.pkg.js' => '3ac6e174',
'core.pkg.js' => 'bd19de1c',
'darkconsole.pkg.js' => '1f9a31bc',
'differential.pkg.css' => '113e692c',
'differential.pkg.js' => '5d53d5ce',
'differential.pkg.js' => 'f6d809c0',
'diffusion.pkg.css' => 'a2d17c7d',
'diffusion.pkg.js' => '6134c5a1',
'favicon.ico' => '30672e08',
@ -396,7 +396,7 @@ return array(
'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '453c5375',
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => 'd4eecc63',
'rsrc/js/application/diff/DiffChangeset.js' => 'b49b59d6',
'rsrc/js/application/diff/DiffChangesetList.js' => '1f2e5265',
'rsrc/js/application/diff/DiffChangesetList.js' => 'e74b7517',
'rsrc/js/application/diff/DiffInline.js' => 'e83d28f3',
'rsrc/js/application/diff/behavior-preview-link.js' => '051c7832',
'rsrc/js/application/differential/behavior-comment-preview.js' => '51c5ad07',
@ -506,7 +506,7 @@ return array(
'rsrc/js/core/behavior-reorder-applications.js' => '76b9fc3e',
'rsrc/js/core/behavior-reveal-content.js' => '60821bc7',
'rsrc/js/core/behavior-scrollbar.js' => '834a1173',
'rsrc/js/core/behavior-search-typeahead.js' => 'd0a99ab4',
'rsrc/js/core/behavior-search-typeahead.js' => 'c3e917d9',
'rsrc/js/core/behavior-select-content.js' => 'bf5374ef',
'rsrc/js/core/behavior-select-on-click.js' => '4e3e79a6',
'rsrc/js/core/behavior-setup-check-https.js' => '491416b3',
@ -528,7 +528,7 @@ return array(
'rsrc/js/phui/behavior-phui-tab-group.js' => '0a0b10e9',
'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8',
'rsrc/js/phuix/PHUIXActionView.js' => '442efd08',
'rsrc/js/phuix/PHUIXAutocomplete.js' => 'e0731603',
'rsrc/js/phuix/PHUIXAutocomplete.js' => '7fa5c915',
'rsrc/js/phuix/PHUIXButtonView.js' => '8a91e1ac',
'rsrc/js/phuix/PHUIXDropdownMenu.js' => '04b2ae03',
'rsrc/js/phuix/PHUIXExample.js' => '68af71ca',
@ -663,7 +663,7 @@ return array(
'javelin-behavior-phabricator-oncopy' => '2926fff2',
'javelin-behavior-phabricator-remarkup-assist' => 'acd29eee',
'javelin-behavior-phabricator-reveal-content' => '60821bc7',
'javelin-behavior-phabricator-search-typeahead' => 'd0a99ab4',
'javelin-behavior-phabricator-search-typeahead' => 'c3e917d9',
'javelin-behavior-phabricator-show-older-transactions' => '8f29b364',
'javelin-behavior-phabricator-tooltips' => 'c420b0b9',
'javelin-behavior-phabricator-transaction-comment-form' => 'b23b49e6',
@ -776,7 +776,7 @@ return array(
'phabricator-darkmessage' => 'c48cccdd',
'phabricator-dashboard-css' => 'fe5b1869',
'phabricator-diff-changeset' => 'b49b59d6',
'phabricator-diff-changeset-list' => '1f2e5265',
'phabricator-diff-changeset-list' => 'e74b7517',
'phabricator-diff-inline' => 'e83d28f3',
'phabricator-drag-and-drop-file-upload' => '58dea2fa',
'phabricator-draggable-list' => 'bea6e7f4',
@ -881,7 +881,7 @@ return array(
'phui-workpanel-view-css' => 'a3a63478',
'phuix-action-list-view' => 'b5c256b8',
'phuix-action-view' => '442efd08',
'phuix-autocomplete' => 'e0731603',
'phuix-autocomplete' => '7fa5c915',
'phuix-button-view' => '8a91e1ac',
'phuix-dropdown-menu' => '04b2ae03',
'phuix-form-control-view' => '16ad6224',
@ -1044,10 +1044,6 @@ return array(
'javelin-uri',
'javelin-routable',
),
'1f2e5265' => array(
'javelin-install',
'phuix-button-view',
),
'1f6794f6' => array(
'javelin-behavior',
'javelin-stratcom',
@ -1561,6 +1557,12 @@ return array(
'7f243deb' => array(
'javelin-install',
),
'7fa5c915' => array(
'javelin-install',
'javelin-dom',
'phuix-icon-view',
'phabricator-prefab',
),
'81144dfa' => array(
'javelin-behavior',
'javelin-behavior-device',
@ -1922,6 +1924,17 @@ return array(
'javelin-dom',
'javelin-vector',
),
'c3e917d9' => array(
'javelin-behavior',
'javelin-typeahead-ondemand-source',
'javelin-typeahead',
'javelin-dom',
'javelin-uri',
'javelin-util',
'javelin-stratcom',
'phabricator-prefab',
'phuix-icon-view',
),
'c420b0b9' => array(
'javelin-behavior',
'javelin-behavior-device',
@ -1973,17 +1986,6 @@ return array(
'phabricator-notification',
'conpherence-thread-manager',
),
'd0a99ab4' => array(
'javelin-behavior',
'javelin-typeahead-ondemand-source',
'javelin-typeahead',
'javelin-dom',
'javelin-uri',
'javelin-util',
'javelin-stratcom',
'phabricator-prefab',
'phuix-icon-view',
),
'd0c516d5' => array(
'javelin-behavior',
'javelin-dom',
@ -2037,12 +2039,6 @@ return array(
'javelin-typeahead-ondemand-source',
'javelin-dom',
),
'e0731603' => array(
'javelin-install',
'javelin-dom',
'phuix-icon-view',
'phabricator-prefab',
),
'e1d25dfb' => array(
'javelin-behavior',
'javelin-stratcom',
@ -2093,6 +2089,10 @@ return array(
'javelin-workflow',
'javelin-magical-init',
),
'e74b7517' => array(
'javelin-install',
'phuix-button-view',
),
'e83d28f3' => array(
'javelin-dom',
),

View file

@ -25,9 +25,9 @@ foreach (new LiskRawMigrationIterator($conn, $src_table) as $row) {
$row['oldLen'],
$row['newOffset'],
$row['newLen'],
DifferentialModernHunk::DATATYPE_TEXT,
DifferentialHunk::DATATYPE_TEXT,
'utf8',
DifferentialModernHunk::DATAFORMAT_RAW,
DifferentialHunk::DATAFORMAT_RAW,
// In rare cases, this could be NULL. See T12090.
(string)$row['changes'],
$row['dateCreated'],

View file

@ -0,0 +1 @@
DROP TABLE {$NAMESPACE}_differential.differential_hunk;

View file

@ -0,0 +1,2 @@
RENAME TABLE {$NAMESPACE}_differential.differential_hunk_modern
TO {$NAMESPACE}_differential.differential_hunk;

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_harbormaster.harbormaster_buildmessage
CHANGE buildTargetPHID receiverPHID VARBINARY(64) NOT NULL;

View file

@ -0,0 +1,27 @@
<?php
$table = new HarbormasterBuildable();
$conn = $table->establishConnection('w');
foreach (new LiskMigrationIterator($table) as $buildable) {
if ($buildable->getBuildableStatus() !== 'building') {
continue;
}
$aborted = queryfx_one(
$conn,
'SELECT * FROM %T WHERE buildablePHID = %s AND buildStatus = %s',
id(new HarbormasterBuild())->getTableName(),
$buildable->getPHID(),
'aborted');
if (!$aborted) {
continue;
}
queryfx(
$conn,
'UPDATE %T SET buildableStatus = %s WHERE id = %d',
$table->getTableName(),
'failed',
$buildable->getID());
}

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_phriction.phriction_content
ADD phid VARBINARY(64) NOT NULL;

View file

@ -0,0 +1,17 @@
<?php
$table = new PhrictionContent();
$conn = $table->establishConnection('w');
foreach (new LiskMigrationIterator($table) as $row) {
if (strlen($row->getPHID())) {
continue;
}
queryfx(
$conn,
'UPDATE %T SET phid = %s WHERE id = %d',
$table->getTableName(),
$table->generatePHID(),
$row->getID());
}

View file

@ -0,0 +1,2 @@
UPDATE {$NAMESPACE}_phriction.phriction_content
SET description = '' WHERE description IS NULL;

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_phriction.phriction_content
CHANGE description description LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT};

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_phriction.phriction_document
CHANGE status status VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT};

View file

@ -0,0 +1,11 @@
UPDATE {$NAMESPACE}_phriction.phriction_document
SET status = 'active' WHERE status = '0';
UPDATE {$NAMESPACE}_phriction.phriction_document
SET status = 'deleted' WHERE status = '1';
UPDATE {$NAMESPACE}_phriction.phriction_document
SET status = 'moved' WHERE status = '2';
UPDATE {$NAMESPACE}_phriction.phriction_document
SET status = 'stub' WHERE status = '3';

View file

@ -2,7 +2,7 @@
<?php
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
require_once $root.'/scripts/init/init-script-with-signals.php';
$args = new PhutilArgumentParser($argv);
$args->setTagline(pht('manage drydock software resources'));

View file

@ -0,0 +1,11 @@
<?php
// Initialize a script that will handle signals.
if (function_exists('pcntl_async_signals')) {
pcntl_async_signals(true);
} else {
declare(ticks = 1);
}
require_once dirname(__FILE__).'/init-script.php';

View file

@ -481,7 +481,6 @@ phutil_register_library_map(array(
'DifferentialInlineCommentQuery' => 'applications/differential/query/DifferentialInlineCommentQuery.php',
'DifferentialJIRAIssuesCommitMessageField' => 'applications/differential/field/DifferentialJIRAIssuesCommitMessageField.php',
'DifferentialJIRAIssuesField' => 'applications/differential/customfield/DifferentialJIRAIssuesField.php',
'DifferentialLegacyHunk' => 'applications/differential/storage/DifferentialLegacyHunk.php',
'DifferentialLegacyQuery' => 'applications/differential/constants/DifferentialLegacyQuery.php',
'DifferentialLineAdjustmentMap' => 'applications/differential/parser/DifferentialLineAdjustmentMap.php',
'DifferentialLintField' => 'applications/differential/customfield/DifferentialLintField.php',
@ -490,7 +489,6 @@ phutil_register_library_map(array(
'DifferentialMailEngineExtension' => 'applications/differential/engineextension/DifferentialMailEngineExtension.php',
'DifferentialMailView' => 'applications/differential/mail/DifferentialMailView.php',
'DifferentialManiphestTasksField' => 'applications/differential/customfield/DifferentialManiphestTasksField.php',
'DifferentialModernHunk' => 'applications/differential/storage/DifferentialModernHunk.php',
'DifferentialParseCacheGarbageCollector' => 'applications/differential/garbagecollector/DifferentialParseCacheGarbageCollector.php',
'DifferentialParseCommitMessageConduitAPIMethod' => 'applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php',
'DifferentialParseRenderTestCase' => 'applications/differential/__tests__/DifferentialParseRenderTestCase.php',
@ -718,6 +716,7 @@ phutil_register_library_map(array(
'DiffusionController' => 'applications/diffusion/controller/DiffusionController.php',
'DiffusionCreateRepositoriesCapability' => 'applications/diffusion/capability/DiffusionCreateRepositoriesCapability.php',
'DiffusionDaemonLockException' => 'applications/diffusion/exception/DiffusionDaemonLockException.php',
'DiffusionDatasourceEngineExtension' => 'applications/diffusion/engineextension/DiffusionDatasourceEngineExtension.php',
'DiffusionDefaultEditCapability' => 'applications/diffusion/capability/DiffusionDefaultEditCapability.php',
'DiffusionDefaultPushCapability' => 'applications/diffusion/capability/DiffusionDefaultPushCapability.php',
'DiffusionDefaultViewCapability' => 'applications/diffusion/capability/DiffusionDefaultViewCapability.php',
@ -813,6 +812,8 @@ phutil_register_library_map(array(
'DiffusionPreCommitContentHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentHeraldField.php',
'DiffusionPreCommitContentMergeHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentMergeHeraldField.php',
'DiffusionPreCommitContentMessageHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentMessageHeraldField.php',
'DiffusionPreCommitContentPackageHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentPackageHeraldField.php',
'DiffusionPreCommitContentPackageOwnerHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentPackageOwnerHeraldField.php',
'DiffusionPreCommitContentPusherHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentPusherHeraldField.php',
'DiffusionPreCommitContentPusherIsCommitterHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentPusherIsCommitterHeraldField.php',
'DiffusionPreCommitContentPusherProjectsHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentPusherProjectsHeraldField.php',
@ -846,7 +847,6 @@ phutil_register_library_map(array(
'DiffusionQueryCommitsConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionQueryCommitsConduitAPIMethod.php',
'DiffusionQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionQueryConduitAPIMethod.php',
'DiffusionQueryPathsConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionQueryPathsConduitAPIMethod.php',
'DiffusionQuickSearchEngineExtension' => 'applications/diffusion/engineextension/DiffusionQuickSearchEngineExtension.php',
'DiffusionRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionRawDiffQuery.php',
'DiffusionRawDiffQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRawDiffQueryConduitAPIMethod.php',
'DiffusionReadmeView' => 'applications/diffusion/view/DiffusionReadmeView.php',
@ -1002,6 +1002,7 @@ phutil_register_library_map(array(
'DoorkeeperSchemaSpec' => 'applications/doorkeeper/storage/DoorkeeperSchemaSpec.php',
'DoorkeeperTagView' => 'applications/doorkeeper/view/DoorkeeperTagView.php',
'DoorkeeperTagsController' => 'applications/doorkeeper/controller/DoorkeeperTagsController.php',
'DrydockAcquiredBrokenResourceException' => 'applications/drydock/exception/DrydockAcquiredBrokenResourceException.php',
'DrydockAlmanacServiceHostBlueprintImplementation' => 'applications/drydock/blueprint/DrydockAlmanacServiceHostBlueprintImplementation.php',
'DrydockApacheWebrootInterface' => 'applications/drydock/interface/webroot/DrydockApacheWebrootInterface.php',
'DrydockAuthorization' => 'applications/drydock/storage/DrydockAuthorization.php',
@ -1043,7 +1044,6 @@ phutil_register_library_map(array(
'DrydockCommandInterface' => 'applications/drydock/interface/command/DrydockCommandInterface.php',
'DrydockCommandQuery' => 'applications/drydock/query/DrydockCommandQuery.php',
'DrydockConsoleController' => 'applications/drydock/controller/DrydockConsoleController.php',
'DrydockConstants' => 'applications/drydock/constants/DrydockConstants.php',
'DrydockController' => 'applications/drydock/controller/DrydockController.php',
'DrydockCreateBlueprintsCapability' => 'applications/drydock/capability/DrydockCreateBlueprintsCapability.php',
'DrydockDAO' => 'applications/drydock/storage/DrydockDAO.php',
@ -1057,6 +1057,7 @@ phutil_register_library_map(array(
'DrydockLeaseActivatedLogType' => 'applications/drydock/logtype/DrydockLeaseActivatedLogType.php',
'DrydockLeaseActivationFailureLogType' => 'applications/drydock/logtype/DrydockLeaseActivationFailureLogType.php',
'DrydockLeaseActivationYieldLogType' => 'applications/drydock/logtype/DrydockLeaseActivationYieldLogType.php',
'DrydockLeaseAllocationFailureLogType' => 'applications/drydock/logtype/DrydockLeaseAllocationFailureLogType.php',
'DrydockLeaseController' => 'applications/drydock/controller/DrydockLeaseController.php',
'DrydockLeaseDatasource' => 'applications/drydock/typeahead/DrydockLeaseDatasource.php',
'DrydockLeaseDestroyedLogType' => 'applications/drydock/logtype/DrydockLeaseDestroyedLogType.php',
@ -1067,6 +1068,7 @@ phutil_register_library_map(array(
'DrydockLeasePHIDType' => 'applications/drydock/phid/DrydockLeasePHIDType.php',
'DrydockLeaseQuery' => 'applications/drydock/query/DrydockLeaseQuery.php',
'DrydockLeaseQueuedLogType' => 'applications/drydock/logtype/DrydockLeaseQueuedLogType.php',
'DrydockLeaseReacquireLogType' => 'applications/drydock/logtype/DrydockLeaseReacquireLogType.php',
'DrydockLeaseReclaimLogType' => 'applications/drydock/logtype/DrydockLeaseReclaimLogType.php',
'DrydockLeaseReleaseController' => 'applications/drydock/controller/DrydockLeaseReleaseController.php',
'DrydockLeaseReleasedLogType' => 'applications/drydock/logtype/DrydockLeaseReleasedLogType.php',
@ -1108,10 +1110,12 @@ phutil_register_library_map(array(
'DrydockResource' => 'applications/drydock/storage/DrydockResource.php',
'DrydockResourceActivationFailureLogType' => 'applications/drydock/logtype/DrydockResourceActivationFailureLogType.php',
'DrydockResourceActivationYieldLogType' => 'applications/drydock/logtype/DrydockResourceActivationYieldLogType.php',
'DrydockResourceAllocationFailureLogType' => 'applications/drydock/logtype/DrydockResourceAllocationFailureLogType.php',
'DrydockResourceController' => 'applications/drydock/controller/DrydockResourceController.php',
'DrydockResourceDatasource' => 'applications/drydock/typeahead/DrydockResourceDatasource.php',
'DrydockResourceListController' => 'applications/drydock/controller/DrydockResourceListController.php',
'DrydockResourceListView' => 'applications/drydock/view/DrydockResourceListView.php',
'DrydockResourceLockException' => 'applications/drydock/exception/DrydockResourceLockException.php',
'DrydockResourcePHIDType' => 'applications/drydock/phid/DrydockResourcePHIDType.php',
'DrydockResourceQuery' => 'applications/drydock/query/DrydockResourceQuery.php',
'DrydockResourceReclaimLogType' => 'applications/drydock/logtype/DrydockResourceReclaimLogType.php',
@ -1274,6 +1278,7 @@ phutil_register_library_map(array(
'HarbormasterBuildablePHIDType' => 'applications/harbormaster/phid/HarbormasterBuildablePHIDType.php',
'HarbormasterBuildableQuery' => 'applications/harbormaster/query/HarbormasterBuildableQuery.php',
'HarbormasterBuildableSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildableSearchEngine.php',
'HarbormasterBuildableStatus' => 'applications/harbormaster/constants/HarbormasterBuildableStatus.php',
'HarbormasterBuildableTransaction' => 'applications/harbormaster/storage/HarbormasterBuildableTransaction.php',
'HarbormasterBuildableTransactionEditor' => 'applications/harbormaster/editor/HarbormasterBuildableTransactionEditor.php',
'HarbormasterBuildableTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildableTransactionQuery.php',
@ -2742,8 +2747,11 @@ phutil_register_library_map(array(
'PhabricatorDatabaseRef' => 'infrastructure/cluster/PhabricatorDatabaseRef.php',
'PhabricatorDatabaseRefParser' => 'infrastructure/cluster/PhabricatorDatabaseRefParser.php',
'PhabricatorDatabaseSetupCheck' => 'applications/config/check/PhabricatorDatabaseSetupCheck.php',
'PhabricatorDatasourceApplicationEngineExtension' => 'applications/meta/engineextension/PhabricatorDatasourceApplicationEngineExtension.php',
'PhabricatorDatasourceEditField' => 'applications/transactions/editfield/PhabricatorDatasourceEditField.php',
'PhabricatorDatasourceEditType' => 'applications/transactions/edittype/PhabricatorDatasourceEditType.php',
'PhabricatorDatasourceEngine' => 'applications/search/engine/PhabricatorDatasourceEngine.php',
'PhabricatorDatasourceEngineExtension' => 'applications/search/engineextension/PhabricatorDatasourceEngineExtension.php',
'PhabricatorDateFormatSetting' => 'applications/settings/setting/PhabricatorDateFormatSetting.php',
'PhabricatorDateTimeSettingsPanel' => 'applications/settings/panel/PhabricatorDateTimeSettingsPanel.php',
'PhabricatorDebugController' => 'applications/system/controller/PhabricatorDebugController.php',
@ -3148,7 +3156,6 @@ phutil_register_library_map(array(
'PhabricatorJSONExportFormat' => 'infrastructure/export/format/PhabricatorJSONExportFormat.php',
'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/PhabricatorJavelinLinter.php',
'PhabricatorJiraIssueHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorJiraIssueHasObjectEdgeType.php',
'PhabricatorJumpNavHandler' => 'applications/search/engine/PhabricatorJumpNavHandler.php',
'PhabricatorKeyValueDatabaseCache' => 'applications/cache/PhabricatorKeyValueDatabaseCache.php',
'PhabricatorKeyValueSerializingCacheProxy' => 'applications/cache/PhabricatorKeyValueSerializingCacheProxy.php',
'PhabricatorKeyboardRemarkupRule' => 'infrastructure/markup/rule/PhabricatorKeyboardRemarkupRule.php',
@ -3313,7 +3320,7 @@ phutil_register_library_map(array(
'PhabricatorMetronomicTriggerClock' => 'infrastructure/daemon/workers/clock/PhabricatorMetronomicTriggerClock.php',
'PhabricatorModularTransaction' => 'applications/transactions/storage/PhabricatorModularTransaction.php',
'PhabricatorModularTransactionType' => 'applications/transactions/storage/PhabricatorModularTransactionType.php',
'PhabricatorMonogramQuickSearchEngineExtension' => 'applications/typeahead/engineextension/PhabricatorMonogramQuickSearchEngineExtension.php',
'PhabricatorMonogramDatasourceEngineExtension' => 'applications/typeahead/engineextension/PhabricatorMonogramDatasourceEngineExtension.php',
'PhabricatorMonospacedFontSetting' => 'applications/settings/setting/PhabricatorMonospacedFontSetting.php',
'PhabricatorMonospacedTextareasSetting' => 'applications/settings/setting/PhabricatorMonospacedTextareasSetting.php',
'PhabricatorMotivatorProfileMenuItem' => 'applications/search/menuitem/PhabricatorMotivatorProfileMenuItem.php',
@ -3415,6 +3422,7 @@ phutil_register_library_map(array(
'PhabricatorObjectRelationshipSource' => 'applications/search/relationship/PhabricatorObjectRelationshipSource.php',
'PhabricatorObjectRemarkupRule' => 'infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php',
'PhabricatorObjectSelectorDialog' => 'view/control/PhabricatorObjectSelectorDialog.php',
'PhabricatorObjectStatus' => 'infrastructure/status/PhabricatorObjectStatus.php',
'PhabricatorOffsetPagedQuery' => 'infrastructure/query/PhabricatorOffsetPagedQuery.php',
'PhabricatorOldWorldContentSource' => 'infrastructure/contentsource/PhabricatorOldWorldContentSource.php',
'PhabricatorOlderInlinesSetting' => 'applications/settings/setting/PhabricatorOlderInlinesSetting.php',
@ -3611,6 +3619,7 @@ phutil_register_library_map(array(
'PhabricatorPeopleCreateController' => 'applications/people/controller/PhabricatorPeopleCreateController.php',
'PhabricatorPeopleCreateGuidanceContext' => 'applications/people/guidance/PhabricatorPeopleCreateGuidanceContext.php',
'PhabricatorPeopleDatasource' => 'applications/people/typeahead/PhabricatorPeopleDatasource.php',
'PhabricatorPeopleDatasourceEngineExtension' => 'applications/people/engineextension/PhabricatorPeopleDatasourceEngineExtension.php',
'PhabricatorPeopleDeleteController' => 'applications/people/controller/PhabricatorPeopleDeleteController.php',
'PhabricatorPeopleDetailsProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleDetailsProfileMenuItem.php',
'PhabricatorPeopleDisableController' => 'applications/people/controller/PhabricatorPeopleDisableController.php',
@ -3643,7 +3652,6 @@ phutil_register_library_map(array(
'PhabricatorPeopleProfileTasksController' => 'applications/people/controller/PhabricatorPeopleProfileTasksController.php',
'PhabricatorPeopleProfileViewController' => 'applications/people/controller/PhabricatorPeopleProfileViewController.php',
'PhabricatorPeopleQuery' => 'applications/people/query/PhabricatorPeopleQuery.php',
'PhabricatorPeopleQuickSearchEngineExtension' => 'applications/people/engineextension/PhabricatorPeopleQuickSearchEngineExtension.php',
'PhabricatorPeopleRenameController' => 'applications/people/controller/PhabricatorPeopleRenameController.php',
'PhabricatorPeopleRevisionsProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleRevisionsProfileMenuItem.php',
'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php',
@ -3906,8 +3914,6 @@ phutil_register_library_map(array(
'PhabricatorQueryOrderItem' => 'infrastructure/query/order/PhabricatorQueryOrderItem.php',
'PhabricatorQueryOrderTestCase' => 'infrastructure/query/order/__tests__/PhabricatorQueryOrderTestCase.php',
'PhabricatorQueryOrderVector' => 'infrastructure/query/order/PhabricatorQueryOrderVector.php',
'PhabricatorQuickSearchApplicationEngineExtension' => 'applications/meta/engineextension/PhabricatorQuickSearchApplicationEngineExtension.php',
'PhabricatorQuickSearchEngine' => 'applications/search/engine/PhabricatorQuickSearchEngine.php',
'PhabricatorQuickSearchEngineExtension' => 'applications/search/engineextension/PhabricatorQuickSearchEngineExtension.php',
'PhabricatorRateLimitRequestExceptionHandler' => 'aphront/handler/PhabricatorRateLimitRequestExceptionHandler.php',
'PhabricatorRecaptchaConfigOptions' => 'applications/config/option/PhabricatorRecaptchaConfigOptions.php',
@ -4377,6 +4383,7 @@ phutil_register_library_map(array(
'PhabricatorTypeaheadMonogramDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadMonogramDatasource.php',
'PhabricatorTypeaheadResult' => 'applications/typeahead/storage/PhabricatorTypeaheadResult.php',
'PhabricatorTypeaheadRuntimeCompositeDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadRuntimeCompositeDatasource.php',
'PhabricatorTypeaheadTestNumbersDatasource' => 'applications/typeahead/datasource/__tests__/PhabricatorTypeaheadTestNumbersDatasource.php',
'PhabricatorTypeaheadTokenView' => 'applications/typeahead/view/PhabricatorTypeaheadTokenView.php',
'PhabricatorUIConfigOptions' => 'applications/config/option/PhabricatorUIConfigOptions.php',
'PhabricatorUIExample' => 'applications/uiexample/examples/PhabricatorUIExample.php',
@ -4840,9 +4847,15 @@ phutil_register_library_map(array(
'PhrictionConduitAPIMethod' => 'applications/phriction/conduit/PhrictionConduitAPIMethod.php',
'PhrictionConstants' => 'applications/phriction/constants/PhrictionConstants.php',
'PhrictionContent' => 'applications/phriction/storage/PhrictionContent.php',
'PhrictionContentPHIDType' => 'applications/phriction/phid/PhrictionContentPHIDType.php',
'PhrictionContentQuery' => 'applications/phriction/query/PhrictionContentQuery.php',
'PhrictionContentSearchConduitAPIMethod' => 'applications/phriction/conduit/PhrictionContentSearchConduitAPIMethod.php',
'PhrictionContentSearchEngine' => 'applications/phriction/query/PhrictionContentSearchEngine.php',
'PhrictionContentSearchEngineAttachment' => 'applications/phriction/engineextension/PhrictionContentSearchEngineAttachment.php',
'PhrictionController' => 'applications/phriction/controller/PhrictionController.php',
'PhrictionCreateConduitAPIMethod' => 'applications/phriction/conduit/PhrictionCreateConduitAPIMethod.php',
'PhrictionDAO' => 'applications/phriction/storage/PhrictionDAO.php',
'PhrictionDatasourceEngineExtension' => 'applications/phriction/engineextension/PhrictionDatasourceEngineExtension.php',
'PhrictionDeleteController' => 'applications/phriction/controller/PhrictionDeleteController.php',
'PhrictionDiffController' => 'applications/phriction/controller/PhrictionDiffController.php',
'PhrictionDocument' => 'applications/phriction/storage/PhrictionDocument.php',
@ -4850,6 +4863,7 @@ phutil_register_library_map(array(
'PhrictionDocumentContentHeraldField' => 'applications/phriction/herald/PhrictionDocumentContentHeraldField.php',
'PhrictionDocumentContentTransaction' => 'applications/phriction/xaction/PhrictionDocumentContentTransaction.php',
'PhrictionDocumentController' => 'applications/phriction/controller/PhrictionDocumentController.php',
'PhrictionDocumentDatasource' => 'applications/phriction/typeahead/PhrictionDocumentDatasource.php',
'PhrictionDocumentDeleteTransaction' => 'applications/phriction/xaction/PhrictionDocumentDeleteTransaction.php',
'PhrictionDocumentFerretEngine' => 'applications/phriction/search/PhrictionDocumentFerretEngine.php',
'PhrictionDocumentFulltextEngine' => 'applications/phriction/search/PhrictionDocumentFulltextEngine.php',
@ -4861,6 +4875,8 @@ phutil_register_library_map(array(
'PhrictionDocumentPHIDType' => 'applications/phriction/phid/PhrictionDocumentPHIDType.php',
'PhrictionDocumentPathHeraldField' => 'applications/phriction/herald/PhrictionDocumentPathHeraldField.php',
'PhrictionDocumentQuery' => 'applications/phriction/query/PhrictionDocumentQuery.php',
'PhrictionDocumentSearchConduitAPIMethod' => 'applications/phriction/conduit/PhrictionDocumentSearchConduitAPIMethod.php',
'PhrictionDocumentSearchEngine' => 'applications/phriction/query/PhrictionDocumentSearchEngine.php',
'PhrictionDocumentStatus' => 'applications/phriction/constants/PhrictionDocumentStatus.php',
'PhrictionDocumentTitleHeraldField' => 'applications/phriction/herald/PhrictionDocumentTitleHeraldField.php',
'PhrictionDocumentTitleTransaction' => 'applications/phriction/xaction/PhrictionDocumentTitleTransaction.php',
@ -4877,7 +4893,6 @@ phutil_register_library_map(array(
'PhrictionRemarkupRule' => 'applications/phriction/markup/PhrictionRemarkupRule.php',
'PhrictionReplyHandler' => 'applications/phriction/mail/PhrictionReplyHandler.php',
'PhrictionSchemaSpec' => 'applications/phriction/storage/PhrictionSchemaSpec.php',
'PhrictionSearchEngine' => 'applications/phriction/query/PhrictionSearchEngine.php',
'PhrictionTransaction' => 'applications/phriction/storage/PhrictionTransaction.php',
'PhrictionTransactionComment' => 'applications/phriction/storage/PhrictionTransactionComment.php',
'PhrictionTransactionEditor' => 'applications/phriction/editor/PhrictionTransactionEditor.php',
@ -4946,12 +4961,12 @@ phutil_register_library_map(array(
'ProjectConduitAPIMethod' => 'applications/project/conduit/ProjectConduitAPIMethod.php',
'ProjectCreateConduitAPIMethod' => 'applications/project/conduit/ProjectCreateConduitAPIMethod.php',
'ProjectCreateProjectsCapability' => 'applications/project/capability/ProjectCreateProjectsCapability.php',
'ProjectDatasourceEngineExtension' => 'applications/project/engineextension/ProjectDatasourceEngineExtension.php',
'ProjectDefaultEditCapability' => 'applications/project/capability/ProjectDefaultEditCapability.php',
'ProjectDefaultJoinCapability' => 'applications/project/capability/ProjectDefaultJoinCapability.php',
'ProjectDefaultViewCapability' => 'applications/project/capability/ProjectDefaultViewCapability.php',
'ProjectEditConduitAPIMethod' => 'applications/project/conduit/ProjectEditConduitAPIMethod.php',
'ProjectQueryConduitAPIMethod' => 'applications/project/conduit/ProjectQueryConduitAPIMethod.php',
'ProjectQuickSearchEngineExtension' => 'applications/project/engineextension/ProjectQuickSearchEngineExtension.php',
'ProjectRemarkupRule' => 'applications/project/remarkup/ProjectRemarkupRule.php',
'ProjectRemarkupRuleTestCase' => 'applications/project/remarkup/__tests__/ProjectRemarkupRuleTestCase.php',
'ProjectReplyHandler' => 'applications/project/mail/ProjectReplyHandler.php',
@ -5644,7 +5659,6 @@ phutil_register_library_map(array(
'DifferentialInlineCommentQuery' => 'PhabricatorOffsetPagedQuery',
'DifferentialJIRAIssuesCommitMessageField' => 'DifferentialCommitMessageCustomField',
'DifferentialJIRAIssuesField' => 'DifferentialStoredCustomField',
'DifferentialLegacyHunk' => 'DifferentialHunk',
'DifferentialLegacyQuery' => 'Phobject',
'DifferentialLineAdjustmentMap' => 'Phobject',
'DifferentialLintField' => 'DifferentialHarbormasterField',
@ -5653,7 +5667,6 @@ phutil_register_library_map(array(
'DifferentialMailEngineExtension' => 'PhabricatorMailEngineExtension',
'DifferentialMailView' => 'Phobject',
'DifferentialManiphestTasksField' => 'DifferentialCoreCustomField',
'DifferentialModernHunk' => 'DifferentialHunk',
'DifferentialParseCacheGarbageCollector' => 'PhabricatorGarbageCollector',
'DifferentialParseCommitMessageConduitAPIMethod' => 'DifferentialConduitAPIMethod',
'DifferentialParseRenderTestCase' => 'PhabricatorTestCase',
@ -5899,6 +5912,7 @@ phutil_register_library_map(array(
'DiffusionController' => 'PhabricatorController',
'DiffusionCreateRepositoriesCapability' => 'PhabricatorPolicyCapability',
'DiffusionDaemonLockException' => 'Exception',
'DiffusionDatasourceEngineExtension' => 'PhabricatorDatasourceEngineExtension',
'DiffusionDefaultEditCapability' => 'PhabricatorPolicyCapability',
'DiffusionDefaultPushCapability' => 'PhabricatorPolicyCapability',
'DiffusionDefaultViewCapability' => 'PhabricatorPolicyCapability',
@ -5997,6 +6011,8 @@ phutil_register_library_map(array(
'DiffusionPreCommitContentHeraldField' => 'HeraldField',
'DiffusionPreCommitContentMergeHeraldField' => 'DiffusionPreCommitContentHeraldField',
'DiffusionPreCommitContentMessageHeraldField' => 'DiffusionPreCommitContentHeraldField',
'DiffusionPreCommitContentPackageHeraldField' => 'DiffusionPreCommitContentHeraldField',
'DiffusionPreCommitContentPackageOwnerHeraldField' => 'DiffusionPreCommitContentHeraldField',
'DiffusionPreCommitContentPusherHeraldField' => 'DiffusionPreCommitContentHeraldField',
'DiffusionPreCommitContentPusherIsCommitterHeraldField' => 'DiffusionPreCommitContentHeraldField',
'DiffusionPreCommitContentPusherProjectsHeraldField' => 'DiffusionPreCommitContentHeraldField',
@ -6030,7 +6046,6 @@ phutil_register_library_map(array(
'DiffusionQueryCommitsConduitAPIMethod' => 'DiffusionConduitAPIMethod',
'DiffusionQueryConduitAPIMethod' => 'DiffusionConduitAPIMethod',
'DiffusionQueryPathsConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
'DiffusionQuickSearchEngineExtension' => 'PhabricatorQuickSearchEngineExtension',
'DiffusionRawDiffQuery' => 'DiffusionFileFutureQuery',
'DiffusionRawDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
'DiffusionReadmeView' => 'DiffusionView',
@ -6200,6 +6215,7 @@ phutil_register_library_map(array(
'DoorkeeperSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'DoorkeeperTagView' => 'AphrontView',
'DoorkeeperTagsController' => 'PhabricatorController',
'DrydockAcquiredBrokenResourceException' => 'Exception',
'DrydockAlmanacServiceHostBlueprintImplementation' => 'DrydockBlueprintImplementation',
'DrydockApacheWebrootInterface' => 'DrydockWebrootInterface',
'DrydockAuthorization' => array(
@ -6259,7 +6275,6 @@ phutil_register_library_map(array(
'DrydockCommandInterface' => 'DrydockInterface',
'DrydockCommandQuery' => 'DrydockQuery',
'DrydockConsoleController' => 'DrydockController',
'DrydockConstants' => 'Phobject',
'DrydockController' => 'PhabricatorController',
'DrydockCreateBlueprintsCapability' => 'PhabricatorPolicyCapability',
'DrydockDAO' => 'PhabricatorLiskDAO',
@ -6276,6 +6291,7 @@ phutil_register_library_map(array(
'DrydockLeaseActivatedLogType' => 'DrydockLogType',
'DrydockLeaseActivationFailureLogType' => 'DrydockLogType',
'DrydockLeaseActivationYieldLogType' => 'DrydockLogType',
'DrydockLeaseAllocationFailureLogType' => 'DrydockLogType',
'DrydockLeaseController' => 'DrydockController',
'DrydockLeaseDatasource' => 'PhabricatorTypeaheadDatasource',
'DrydockLeaseDestroyedLogType' => 'DrydockLogType',
@ -6286,11 +6302,12 @@ phutil_register_library_map(array(
'DrydockLeasePHIDType' => 'PhabricatorPHIDType',
'DrydockLeaseQuery' => 'DrydockQuery',
'DrydockLeaseQueuedLogType' => 'DrydockLogType',
'DrydockLeaseReacquireLogType' => 'DrydockLogType',
'DrydockLeaseReclaimLogType' => 'DrydockLogType',
'DrydockLeaseReleaseController' => 'DrydockLeaseController',
'DrydockLeaseReleasedLogType' => 'DrydockLogType',
'DrydockLeaseSearchEngine' => 'PhabricatorApplicationSearchEngine',
'DrydockLeaseStatus' => 'DrydockConstants',
'DrydockLeaseStatus' => 'PhabricatorObjectStatus',
'DrydockLeaseUpdateWorker' => 'DrydockWorker',
'DrydockLeaseViewController' => 'DrydockLeaseController',
'DrydockLeaseWaitingForResourcesLogType' => 'DrydockLogType',
@ -6336,16 +6353,18 @@ phutil_register_library_map(array(
),
'DrydockResourceActivationFailureLogType' => 'DrydockLogType',
'DrydockResourceActivationYieldLogType' => 'DrydockLogType',
'DrydockResourceAllocationFailureLogType' => 'DrydockLogType',
'DrydockResourceController' => 'DrydockController',
'DrydockResourceDatasource' => 'PhabricatorTypeaheadDatasource',
'DrydockResourceListController' => 'DrydockResourceController',
'DrydockResourceListView' => 'AphrontView',
'DrydockResourceLockException' => 'Exception',
'DrydockResourcePHIDType' => 'PhabricatorPHIDType',
'DrydockResourceQuery' => 'DrydockQuery',
'DrydockResourceReclaimLogType' => 'DrydockLogType',
'DrydockResourceReleaseController' => 'DrydockResourceController',
'DrydockResourceSearchEngine' => 'PhabricatorApplicationSearchEngine',
'DrydockResourceStatus' => 'DrydockConstants',
'DrydockResourceStatus' => 'PhabricatorObjectStatus',
'DrydockResourceUpdateWorker' => 'DrydockWorker',
'DrydockResourceViewController' => 'DrydockResourceController',
'DrydockSFTPFilesystemInterface' => 'DrydockFilesystemInterface',
@ -6553,6 +6572,7 @@ phutil_register_library_map(array(
'HarbormasterBuildablePHIDType' => 'PhabricatorPHIDType',
'HarbormasterBuildableQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HarbormasterBuildableSearchEngine' => 'PhabricatorApplicationSearchEngine',
'HarbormasterBuildableStatus' => 'Phobject',
'HarbormasterBuildableTransaction' => 'PhabricatorApplicationTransaction',
'HarbormasterBuildableTransactionEditor' => 'PhabricatorApplicationTransactionEditor',
'HarbormasterBuildableTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
@ -8247,8 +8267,11 @@ phutil_register_library_map(array(
'PhabricatorDatabaseRef' => 'Phobject',
'PhabricatorDatabaseRefParser' => 'Phobject',
'PhabricatorDatabaseSetupCheck' => 'PhabricatorSetupCheck',
'PhabricatorDatasourceApplicationEngineExtension' => 'PhabricatorDatasourceEngineExtension',
'PhabricatorDatasourceEditField' => 'PhabricatorTokenizerEditField',
'PhabricatorDatasourceEditType' => 'PhabricatorPHIDListEditType',
'PhabricatorDatasourceEngine' => 'Phobject',
'PhabricatorDatasourceEngineExtension' => 'Phobject',
'PhabricatorDateFormatSetting' => 'PhabricatorSelectSetting',
'PhabricatorDateTimeSettingsPanel' => 'PhabricatorEditEngineSettingsPanel',
'PhabricatorDebugController' => 'PhabricatorController',
@ -8697,7 +8720,6 @@ phutil_register_library_map(array(
'PhabricatorJSONExportFormat' => 'PhabricatorExportFormat',
'PhabricatorJavelinLinter' => 'ArcanistLinter',
'PhabricatorJiraIssueHasObjectEdgeType' => 'PhabricatorEdgeType',
'PhabricatorJumpNavHandler' => 'Phobject',
'PhabricatorKeyValueDatabaseCache' => 'PhutilKeyValueCache',
'PhabricatorKeyValueSerializingCacheProxy' => 'PhutilKeyValueCacheProxy',
'PhabricatorKeyboardRemarkupRule' => 'PhutilRemarkupRule',
@ -8873,7 +8895,7 @@ phutil_register_library_map(array(
'PhabricatorMetronomicTriggerClock' => 'PhabricatorTriggerClock',
'PhabricatorModularTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorModularTransactionType' => 'Phobject',
'PhabricatorMonogramQuickSearchEngineExtension' => 'PhabricatorQuickSearchEngineExtension',
'PhabricatorMonogramDatasourceEngineExtension' => 'PhabricatorDatasourceEngineExtension',
'PhabricatorMonospacedFontSetting' => 'PhabricatorStringSetting',
'PhabricatorMonospacedTextareasSetting' => 'PhabricatorSelectSetting',
'PhabricatorMotivatorProfileMenuItem' => 'PhabricatorProfileMenuItem',
@ -8992,6 +9014,7 @@ phutil_register_library_map(array(
'PhabricatorObjectRelationshipSource' => 'Phobject',
'PhabricatorObjectRemarkupRule' => 'PhutilRemarkupRule',
'PhabricatorObjectSelectorDialog' => 'Phobject',
'PhabricatorObjectStatus' => 'Phobject',
'PhabricatorOffsetPagedQuery' => 'PhabricatorQuery',
'PhabricatorOldWorldContentSource' => 'PhabricatorContentSource',
'PhabricatorOlderInlinesSetting' => 'PhabricatorSelectSetting',
@ -9240,6 +9263,7 @@ phutil_register_library_map(array(
'PhabricatorPeopleCreateController' => 'PhabricatorPeopleController',
'PhabricatorPeopleCreateGuidanceContext' => 'PhabricatorGuidanceContext',
'PhabricatorPeopleDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorPeopleDatasourceEngineExtension' => 'PhabricatorDatasourceEngineExtension',
'PhabricatorPeopleDeleteController' => 'PhabricatorPeopleController',
'PhabricatorPeopleDetailsProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorPeopleDisableController' => 'PhabricatorPeopleController',
@ -9272,7 +9296,6 @@ phutil_register_library_map(array(
'PhabricatorPeopleProfileTasksController' => 'PhabricatorPeopleProfileController',
'PhabricatorPeopleProfileViewController' => 'PhabricatorPeopleProfileController',
'PhabricatorPeopleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorPeopleQuickSearchEngineExtension' => 'PhabricatorQuickSearchEngineExtension',
'PhabricatorPeopleRenameController' => 'PhabricatorPeopleController',
'PhabricatorPeopleRevisionsProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine',
@ -9590,9 +9613,7 @@ phutil_register_library_map(array(
'Phobject',
'Iterator',
),
'PhabricatorQuickSearchApplicationEngineExtension' => 'PhabricatorQuickSearchEngineExtension',
'PhabricatorQuickSearchEngine' => 'Phobject',
'PhabricatorQuickSearchEngineExtension' => 'Phobject',
'PhabricatorQuickSearchEngineExtension' => 'PhabricatorDatasourceEngineExtension',
'PhabricatorRateLimitRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler',
'PhabricatorRecaptchaConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorRedirectController' => 'PhabricatorController',
@ -10151,6 +10172,7 @@ phutil_register_library_map(array(
'PhabricatorTypeaheadMonogramDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorTypeaheadResult' => 'Phobject',
'PhabricatorTypeaheadRuntimeCompositeDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'PhabricatorTypeaheadTestNumbersDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorTypeaheadTokenView' => 'AphrontTagView',
'PhabricatorUIConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorUIExample' => 'Phobject',
@ -10745,11 +10767,19 @@ phutil_register_library_map(array(
'PhrictionConstants' => 'Phobject',
'PhrictionContent' => array(
'PhrictionDAO',
'PhabricatorMarkupInterface',
'PhabricatorPolicyInterface',
'PhabricatorDestructibleInterface',
'PhabricatorConduitResultInterface',
),
'PhrictionContentPHIDType' => 'PhabricatorPHIDType',
'PhrictionContentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhrictionContentSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'PhrictionContentSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhrictionContentSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
'PhrictionController' => 'PhabricatorController',
'PhrictionCreateConduitAPIMethod' => 'PhrictionConduitAPIMethod',
'PhrictionDAO' => 'PhabricatorLiskDAO',
'PhrictionDatasourceEngineExtension' => 'PhabricatorDatasourceEngineExtension',
'PhrictionDeleteController' => 'PhrictionController',
'PhrictionDiffController' => 'PhrictionController',
'PhrictionDocument' => array(
@ -10763,11 +10793,13 @@ phutil_register_library_map(array(
'PhabricatorFerretInterface',
'PhabricatorProjectInterface',
'PhabricatorApplicationTransactionInterface',
'PhabricatorConduitResultInterface',
),
'PhrictionDocumentAuthorHeraldField' => 'PhrictionDocumentHeraldField',
'PhrictionDocumentContentHeraldField' => 'PhrictionDocumentHeraldField',
'PhrictionDocumentContentTransaction' => 'PhrictionDocumentTransactionType',
'PhrictionDocumentController' => 'PhrictionController',
'PhrictionDocumentDatasource' => 'PhabricatorTypeaheadDatasource',
'PhrictionDocumentDeleteTransaction' => 'PhrictionDocumentTransactionType',
'PhrictionDocumentFerretEngine' => 'PhabricatorFerretEngine',
'PhrictionDocumentFulltextEngine' => 'PhabricatorFulltextEngine',
@ -10779,7 +10811,9 @@ phutil_register_library_map(array(
'PhrictionDocumentPHIDType' => 'PhabricatorPHIDType',
'PhrictionDocumentPathHeraldField' => 'PhrictionDocumentHeraldField',
'PhrictionDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhrictionDocumentStatus' => 'PhrictionConstants',
'PhrictionDocumentSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'PhrictionDocumentSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhrictionDocumentStatus' => 'PhabricatorObjectStatus',
'PhrictionDocumentTitleHeraldField' => 'PhrictionDocumentHeraldField',
'PhrictionDocumentTitleTransaction' => 'PhrictionDocumentTransactionType',
'PhrictionDocumentTransactionType' => 'PhabricatorModularTransactionType',
@ -10795,7 +10829,6 @@ phutil_register_library_map(array(
'PhrictionRemarkupRule' => 'PhutilRemarkupRule',
'PhrictionReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
'PhrictionSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PhrictionSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhrictionTransaction' => 'PhabricatorModularTransaction',
'PhrictionTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PhrictionTransactionEditor' => 'PhabricatorApplicationTransactionEditor',
@ -10885,12 +10918,12 @@ phutil_register_library_map(array(
'ProjectConduitAPIMethod' => 'ConduitAPIMethod',
'ProjectCreateConduitAPIMethod' => 'ProjectConduitAPIMethod',
'ProjectCreateProjectsCapability' => 'PhabricatorPolicyCapability',
'ProjectDatasourceEngineExtension' => 'PhabricatorDatasourceEngineExtension',
'ProjectDefaultEditCapability' => 'PhabricatorPolicyCapability',
'ProjectDefaultJoinCapability' => 'PhabricatorPolicyCapability',
'ProjectDefaultViewCapability' => 'PhabricatorPolicyCapability',
'ProjectEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'ProjectQueryConduitAPIMethod' => 'ProjectConduitAPIMethod',
'ProjectQuickSearchEngineExtension' => 'PhabricatorQuickSearchEngineExtension',
'ProjectRemarkupRule' => 'PhabricatorObjectRemarkupRule',
'ProjectRemarkupRuleTestCase' => 'PhabricatorTestCase',
'ProjectReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',

View file

@ -300,6 +300,10 @@ final class PhabricatorAuthPasswordEngine
$password->upgradePasswordHasher($envelope, $this->getObject());
$new_hasher = $password->getHasher();
// NOTE: We must save the change before applying transactions because
// the editor will reload the object to obtain a read lock.
$password->save();
$xactions = array();
$xactions[] = $password->getApplicationTransactionTemplate()

View file

@ -37,6 +37,24 @@ final class PhabricatorCoreConfigOptions
$proto_doc_name = pht('User Guide: Prototype Applications');
$applications_app_href = '/applications/';
$silent_description = $this->deformat(pht(<<<EOREMARKUP
This option allows you to stop Phabricator from sending data to most external
services: it will disable email, SMS, repository mirroring, remote builds,
Doorkeeper writes, and webhooks.
This option is intended to allow a Phabricator instance to be exported, copied,
imported, and run in a test environment without impacting users. For example,
if you are migrating to new hardware, you could perform a test migration first
with this flag set, make sure things work, and then do a production cutover
later with higher confidence and less disruption.
Without making use of this flag to silence the temporary test environment,
users would receive duplicate email during the time the test instance and old
production instance were both in operation.
EOREMARKUP
));
return array(
$this->newOption('phabricator.base-uri', 'string', null)
->setLocked(true)
@ -232,21 +250,7 @@ final class PhabricatorCoreConfigOptions
pht('Run Normally'),
))
->setSummary(pht('Stop Phabricator from sending any email, etc.'))
->setDescription(
pht(
'This option allows you to stop Phabricator from sending '.
'any data to external services. Among other things, it will '.
'disable email, SMS, repository mirroring, and HTTP hooks.'.
"\n\n".
'This option is intended to allow a Phabricator instance to '.
'be exported, copied, imported, and run in a test environment '.
'without impacting users. For example, if you are migrating '.
'to new hardware, you could perform a test migration first, '.
'make sure things work, and then do a production cutover '.
'later with higher confidence and less disruption. Without '.
'this flag, users would receive duplicate email during the '.
'time the test instance and old production instance were '.
'both in operation.')),
->setDescription($silent_description),
);
}

View file

@ -99,24 +99,6 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
return pht('%s created this room.', $author);
}
/**
* We really only need a read lock if we have a comment. In that case, we
* must update the messagesCount field on the conpherence and
* seenMessagesCount(s) for the participant(s).
*/
protected function shouldReadLock(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$lock = false;
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
$lock = true;
break;
}
return $lock;
}
protected function applyBuiltinInternalTransaction(
PhabricatorLiskDAO $object,

View file

@ -44,12 +44,12 @@ final class DifferentialUnitField
->executeOne();
if ($buildable) {
switch ($buildable->getBuildableStatus()) {
case HarbormasterBuildable::STATUS_BUILDING:
case HarbormasterBuildableStatus::STATUS_BUILDING:
$warnings[] = pht(
'These changes have not finished building yet and may have build '.
'failures.');
break;
case HarbormasterBuildable::STATUS_FAILED:
case HarbormasterBuildableStatus::STATUS_FAILED:
$warnings[] = pht(
'These changes have failed to build.');
break;

View file

@ -365,21 +365,22 @@ final class DifferentialTransactionEditor
$diff->setRevisionID($object->getID());
$diff->save();
// Update Harbormaster to set the containerPHID correctly for any
// existing buildables. We may otherwise have buildables stuck with
// the old (`null`) container.
// If there are any outstanding buildables for this diff, tell
// Harbormaster that their containers need to be updated. This is
// common, because `arc` creates buildables so it can upload lint
// and unit results.
// TODO: This is a bit iffy, maybe we can find a cleaner approach?
// In particular, this could (rarely) be overwritten by Harbormaster
// workers.
$table = new HarbormasterBuildable();
$conn_w = $table->establishConnection('w');
queryfx(
$conn_w,
'UPDATE %T SET containerPHID = %s WHERE buildablePHID = %s',
$table->getTableName(),
$object->getPHID(),
$diff->getPHID());
$buildables = id(new HarbormasterBuildableQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withManualBuildables(false)
->withBuildablePHIDs(array($diff->getPHID()))
->execute();
foreach ($buildables as $buildable) {
$buildable->sendMessage(
$this->getActor(),
HarbormasterMessageType::BUILDABLE_CONTAINER,
true);
}
return;
}

View file

@ -217,8 +217,8 @@ final class DifferentialDiffExtractionEngine extends Phobject {
// -echo "test";
// -(empty line)
$hunk = id(new DifferentialModernHunk())->setChanges($context);
$vs_hunk = id(new DifferentialModernHunk())->setChanges($vs_context);
$hunk = id(new DifferentialHunk())->setChanges($context);
$vs_hunk = id(new DifferentialHunk())->setChanges($vs_context);
if ($hunk->makeOldFile() != $vs_hunk->makeOldFile() ||
$hunk->makeNewFile() != $vs_hunk->makeNewFile()) {
return true;

View file

@ -57,4 +57,8 @@ final class HeraldDifferentialDiffAdapter extends HeraldDifferentialAdapter {
return pht('New Diff');
}
public function supportsWebhooks() {
return false;
}
}

View file

@ -32,8 +32,8 @@ final class PhabricatorDifferentialMigrateHunkWorkflow
$storage = $args->getArg('to');
switch ($storage) {
case DifferentialModernHunk::DATATYPE_TEXT:
case DifferentialModernHunk::DATATYPE_FILE:
case DifferentialHunk::DATATYPE_TEXT:
case DifferentialHunk::DATATYPE_FILE:
break;
default:
throw new PhutilArgumentUsageException(
@ -44,13 +44,13 @@ final class PhabricatorDifferentialMigrateHunkWorkflow
$old_data = $hunk->getChanges();
switch ($storage) {
case DifferentialModernHunk::DATATYPE_TEXT:
case DifferentialHunk::DATATYPE_TEXT:
$hunk->saveAsText();
$this->logOkay(
pht('TEXT'),
pht('Convereted hunk to text storage.'));
break;
case DifferentialModernHunk::DATATYPE_FILE:
case DifferentialHunk::DATATYPE_FILE:
$hunk->saveAsFile();
$this->logOkay(
pht('FILE'),
@ -71,7 +71,7 @@ final class PhabricatorDifferentialMigrateHunkWorkflow
}
private function loadHunk($id) {
$hunk = id(new DifferentialModernHunk())->load($id);
$hunk = id(new DifferentialHunk())->load($id);
if (!$hunk) {
throw new PhutilArgumentUsageException(
pht(

View file

@ -3,7 +3,7 @@
final class DifferentialChangesetParserTestCase extends PhabricatorTestCase {
public function testDiffChangesets() {
$hunk = new DifferentialModernHunk();
$hunk = new DifferentialHunk();
$hunk->setChanges("+a\n b\n-c");
$hunk->setNewOffset(1);
$hunk->setNewLen(2);
@ -20,7 +20,7 @@ final class DifferentialChangesetParserTestCase extends PhabricatorTestCase {
);
foreach ($tests as $changes => $expected) {
$hunk = new DifferentialModernHunk();
$hunk = new DifferentialHunk();
$hunk->setChanges($changes);
$hunk->setNewOffset(11);
$hunk->setNewLen(3);

View file

@ -14,7 +14,7 @@ final class DifferentialHunkParserTestCase extends PhabricatorTestCase {
$new_len,
$changes) {
$hunk = id(new DifferentialModernHunk())
$hunk = id(new DifferentialHunk())
->setOldOffset($old_offset)
->setOldLen($old_len)
->setNewOffset($new_offset)

View file

@ -30,25 +30,12 @@ final class DifferentialHunkQuery
}
}
public function newResultObject() {
return new DifferentialHunk();
}
protected function loadPage() {
$all_results = array();
// Load modern hunks.
$table = new DifferentialModernHunk();
$conn_r = $table->establishConnection('r');
$modern_data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$modern_results = $table->loadAllFromArray($modern_data);
// Strip all the IDs off since they're not unique and nothing should be
// using them.
return array_values($modern_results);
return $this->loadStandardPage($this->newResultObject());
}
protected function willFilterPage(array $hunks) {
@ -76,8 +63,8 @@ final class DifferentialHunkQuery
return $hunks;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if (!$this->changesets) {
throw new Exception(
@ -87,13 +74,11 @@ final class DifferentialHunkQuery
}
$where[] = qsprintf(
$conn_r,
$conn,
'changesetID IN (%Ld)',
mpull($this->changesets, 'getID'));
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
return $where;
}
public function getQueryApplicationClass() {

View file

@ -118,11 +118,11 @@ final class DifferentialChangeset
public function delete() {
$this->openTransaction();
$modern_hunks = id(new DifferentialModernHunk())->loadAllWhere(
$hunks = id(new DifferentialHunk())->loadAllWhere(
'changesetID = %d',
$this->getID());
foreach ($modern_hunks as $modern_hunk) {
$modern_hunk->delete();
foreach ($hunks as $hunk) {
$hunk->delete();
}
$this->unsavedHunks = array();
@ -292,7 +292,7 @@ final class DifferentialChangeset
PhabricatorDestructionEngine $engine) {
$this->openTransaction();
$hunks = id(new DifferentialModernHunk())->loadAllWhere(
$hunks = id(new DifferentialHunk())->loadAllWhere(
'changesetID = %d',
$this->getID());
foreach ($hunks as $hunk) {

View file

@ -189,7 +189,7 @@ final class DifferentialDiff
$hunks = $change->getHunks();
if ($hunks) {
foreach ($hunks as $hunk) {
$dhunk = new DifferentialModernHunk();
$dhunk = new DifferentialHunk();
$dhunk->setOldOffset($hunk->getOldOffset());
$dhunk->setOldLen($hunk->getOldLength());
$dhunk->setNewOffset($hunk->getNewOffset());

View file

@ -1,6 +1,6 @@
<?php
abstract class DifferentialHunk
final class DifferentialHunk
extends DifferentialDAO
implements
PhabricatorPolicyInterface,
@ -11,16 +11,55 @@ abstract class DifferentialHunk
protected $oldLen;
protected $newOffset;
protected $newLen;
protected $dataType;
protected $dataEncoding;
protected $dataFormat;
protected $data;
private $changeset;
private $splitLines;
private $structuredLines;
private $structuredFiles = array();
private $rawData;
private $forcedEncoding;
private $fileData;
const FLAG_LINES_ADDED = 1;
const FLAG_LINES_REMOVED = 2;
const FLAG_LINES_STABLE = 4;
const DATATYPE_TEXT = 'text';
const DATATYPE_FILE = 'file';
const DATAFORMAT_RAW = 'byte';
const DATAFORMAT_DEFLATED = 'gzde';
protected function getConfiguration() {
return array(
self::CONFIG_BINARY => array(
'data' => true,
),
self::CONFIG_COLUMN_SCHEMA => array(
'dataType' => 'bytes4',
'dataEncoding' => 'text16?',
'dataFormat' => 'bytes4',
'oldOffset' => 'uint32',
'oldLen' => 'uint32',
'newOffset' => 'uint32',
'newLen' => 'uint32',
),
self::CONFIG_KEY_SCHEMA => array(
'key_changeset' => array(
'columns' => array('changesetID'),
),
'key_created' => array(
'columns' => array('dateCreated'),
),
),
) + parent::getConfiguration();
}
public function getAddedLines() {
return $this->makeContent($include = '+');
}
@ -214,6 +253,197 @@ abstract class DifferentialHunk
}
/* -( Storage )------------------------------------------------------------ */
public function setChanges($text) {
$this->rawData = $text;
$this->dataEncoding = $this->detectEncodingForStorage($text);
$this->dataType = self::DATATYPE_TEXT;
list($format, $data) = $this->formatDataForStorage($text);
$this->dataFormat = $format;
$this->data = $data;
return $this;
}
public function getChanges() {
return $this->getUTF8StringFromStorage(
$this->getRawData(),
nonempty($this->forcedEncoding, $this->getDataEncoding()));
}
public function forceEncoding($encoding) {
$this->forcedEncoding = $encoding;
return $this;
}
private function formatDataForStorage($data) {
$deflated = PhabricatorCaches::maybeDeflateData($data);
if ($deflated !== null) {
return array(self::DATAFORMAT_DEFLATED, $deflated);
}
return array(self::DATAFORMAT_RAW, $data);
}
public function saveAsText() {
$old_type = $this->getDataType();
$old_data = $this->getData();
if ($old_type == self::DATATYPE_TEXT) {
return $this;
}
$raw_data = $this->getRawData();
$this->setDataType(self::DATATYPE_TEXT);
list($format, $data) = $this->formatDataForStorage($raw_data);
$this->setDataFormat($format);
$this->setData($data);
$result = $this->save();
$this->destroyData($old_type, $old_data);
return $result;
}
public function saveAsFile() {
$old_type = $this->getDataType();
$old_data = $this->getData();
if ($old_type == self::DATATYPE_FILE) {
return $this;
}
$raw_data = $this->getRawData();
list($format, $data) = $this->formatDataForStorage($raw_data);
$this->setDataFormat($format);
$file = PhabricatorFile::newFromFileData(
$data,
array(
'name' => 'differential-hunk',
'mime-type' => 'application/octet-stream',
'viewPolicy' => PhabricatorPolicies::POLICY_NOONE,
));
$this->setDataType(self::DATATYPE_FILE);
$this->setData($file->getPHID());
// NOTE: Because hunks don't have a PHID and we just load hunk data with
// the omnipotent viewer, we do not need to attach the file to anything.
$result = $this->save();
$this->destroyData($old_type, $old_data);
return $result;
}
private function getRawData() {
if ($this->rawData === null) {
$type = $this->getDataType();
$data = $this->getData();
switch ($type) {
case self::DATATYPE_TEXT:
// In this storage type, the changes are stored on the object.
$data = $data;
break;
case self::DATATYPE_FILE:
$data = $this->loadFileData();
break;
default:
throw new Exception(
pht('Hunk has unsupported data type "%s"!', $type));
}
$format = $this->getDataFormat();
switch ($format) {
case self::DATAFORMAT_RAW:
// In this format, the changes are stored as-is.
$data = $data;
break;
case self::DATAFORMAT_DEFLATED:
$data = PhabricatorCaches::inflateData($data);
break;
default:
throw new Exception(
pht('Hunk has unsupported data encoding "%s"!', $type));
}
$this->rawData = $data;
}
return $this->rawData;
}
private function loadFileData() {
if ($this->fileData === null) {
$type = $this->getDataType();
if ($type !== self::DATATYPE_FILE) {
throw new Exception(
pht(
'Unable to load file data for hunk with wrong data type ("%s").',
$type));
}
$file_phid = $this->getData();
$file = $this->loadRawFile($file_phid);
$data = $file->loadFileData();
$this->fileData = $data;
}
return $this->fileData;
}
private function loadRawFile($file_phid) {
$viewer = PhabricatorUser::getOmnipotentUser();
$files = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($file_phid))
->execute();
if (!$files) {
throw new Exception(
pht(
'Failed to load file ("%s") with hunk data.',
$file_phid));
}
$file = head($files);
return $file;
}
private function destroyData(
$type,
$data,
PhabricatorDestructionEngine $engine = null) {
if (!$engine) {
$engine = new PhabricatorDestructionEngine();
}
switch ($type) {
case self::DATATYPE_FILE:
$file = $this->loadRawFile($data);
$engine->destroyObject($file);
break;
}
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
@ -237,8 +467,13 @@ abstract class DifferentialHunk
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$type = $this->getDataType();
$data = $this->getData();
$this->destroyData($type, $data, $engine);
$this->delete();
}
}

View file

@ -1,37 +0,0 @@
<?php
final class DifferentialLegacyHunk extends DifferentialHunk {
protected $changes;
protected function getConfiguration() {
return array(
self::CONFIG_COLUMN_SCHEMA => array(
'changes' => 'text?',
'oldOffset' => 'uint32',
'oldLen' => 'uint32',
'newOffset' => 'uint32',
'newLen' => 'uint32',
),
self::CONFIG_KEY_SCHEMA => array(
'changesetID' => array(
'columns' => array('changesetID'),
),
),
) + parent::getConfiguration();
}
public function getTableName() {
return 'differential_hunk';
}
public function getDataEncoding() {
return 'utf8';
}
public function forceEncoding($encoding) {
// Not supported, these are always utf8.
return $this;
}
}

View file

@ -1,249 +0,0 @@
<?php
final class DifferentialModernHunk extends DifferentialHunk {
const DATATYPE_TEXT = 'text';
const DATATYPE_FILE = 'file';
const DATAFORMAT_RAW = 'byte';
const DATAFORMAT_DEFLATED = 'gzde';
protected $dataType;
protected $dataEncoding;
protected $dataFormat;
protected $data;
private $rawData;
private $forcedEncoding;
private $fileData;
public function getTableName() {
return 'differential_hunk_modern';
}
protected function getConfiguration() {
return array(
self::CONFIG_BINARY => array(
'data' => true,
),
self::CONFIG_COLUMN_SCHEMA => array(
'dataType' => 'bytes4',
'dataEncoding' => 'text16?',
'dataFormat' => 'bytes4',
'oldOffset' => 'uint32',
'oldLen' => 'uint32',
'newOffset' => 'uint32',
'newLen' => 'uint32',
),
self::CONFIG_KEY_SCHEMA => array(
'key_changeset' => array(
'columns' => array('changesetID'),
),
'key_created' => array(
'columns' => array('dateCreated'),
),
),
) + parent::getConfiguration();
}
public function setChanges($text) {
$this->rawData = $text;
$this->dataEncoding = $this->detectEncodingForStorage($text);
$this->dataType = self::DATATYPE_TEXT;
list($format, $data) = $this->formatDataForStorage($text);
$this->dataFormat = $format;
$this->data = $data;
return $this;
}
public function getChanges() {
return $this->getUTF8StringFromStorage(
$this->getRawData(),
nonempty($this->forcedEncoding, $this->getDataEncoding()));
}
public function forceEncoding($encoding) {
$this->forcedEncoding = $encoding;
return $this;
}
private function formatDataForStorage($data) {
$deflated = PhabricatorCaches::maybeDeflateData($data);
if ($deflated !== null) {
return array(self::DATAFORMAT_DEFLATED, $deflated);
}
return array(self::DATAFORMAT_RAW, $data);
}
public function saveAsText() {
$old_type = $this->getDataType();
$old_data = $this->getData();
if ($old_type == self::DATATYPE_TEXT) {
return $this;
}
$raw_data = $this->getRawData();
$this->setDataType(self::DATATYPE_TEXT);
list($format, $data) = $this->formatDataForStorage($raw_data);
$this->setDataFormat($format);
$this->setData($data);
$result = $this->save();
$this->destroyData($old_type, $old_data);
return $result;
}
public function saveAsFile() {
$old_type = $this->getDataType();
$old_data = $this->getData();
if ($old_type == self::DATATYPE_FILE) {
return $this;
}
$raw_data = $this->getRawData();
list($format, $data) = $this->formatDataForStorage($raw_data);
$this->setDataFormat($format);
$file = PhabricatorFile::newFromFileData(
$data,
array(
'name' => 'differential-hunk',
'mime-type' => 'application/octet-stream',
'viewPolicy' => PhabricatorPolicies::POLICY_NOONE,
));
$this->setDataType(self::DATATYPE_FILE);
$this->setData($file->getPHID());
// NOTE: Because hunks don't have a PHID and we just load hunk data with
// the omnipotent viewer, we do not need to attach the file to anything.
$result = $this->save();
$this->destroyData($old_type, $old_data);
return $result;
}
private function getRawData() {
if ($this->rawData === null) {
$type = $this->getDataType();
$data = $this->getData();
switch ($type) {
case self::DATATYPE_TEXT:
// In this storage type, the changes are stored on the object.
$data = $data;
break;
case self::DATATYPE_FILE:
$data = $this->loadFileData();
break;
default:
throw new Exception(
pht('Hunk has unsupported data type "%s"!', $type));
}
$format = $this->getDataFormat();
switch ($format) {
case self::DATAFORMAT_RAW:
// In this format, the changes are stored as-is.
$data = $data;
break;
case self::DATAFORMAT_DEFLATED:
$data = PhabricatorCaches::inflateData($data);
break;
default:
throw new Exception(
pht('Hunk has unsupported data encoding "%s"!', $type));
}
$this->rawData = $data;
}
return $this->rawData;
}
private function loadFileData() {
if ($this->fileData === null) {
$type = $this->getDataType();
if ($type !== self::DATATYPE_FILE) {
throw new Exception(
pht(
'Unable to load file data for hunk with wrong data type ("%s").',
$type));
}
$file_phid = $this->getData();
$file = $this->loadRawFile($file_phid);
$data = $file->loadFileData();
$this->fileData = $data;
}
return $this->fileData;
}
private function loadRawFile($file_phid) {
$viewer = PhabricatorUser::getOmnipotentUser();
$files = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($file_phid))
->execute();
if (!$files) {
throw new Exception(
pht(
'Failed to load file ("%s") with hunk data.',
$file_phid));
}
$file = head($files);
return $file;
}
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$type = $this->getDataType();
$data = $this->getData();
$this->destroyData($type, $data, $engine);
return parent::destroyObjectPermanently($engine);
}
private function destroyData(
$type,
$data,
PhabricatorDestructionEngine $engine = null) {
if (!$engine) {
$engine = new PhabricatorDestructionEngine();
}
switch ($type) {
case self::DATATYPE_FILE:
$file = $this->loadRawFile($data);
$engine->destroyObject($file);
break;
}
}
}

View file

@ -743,9 +743,10 @@ final class DifferentialRevision extends DifferentialDAO
public function loadActiveBuilds(PhabricatorUser $viewer) {
$diff = $this->getActiveDiff();
// NOTE: We can't use `withContainerPHIDs()` here because the container
// update in Harbormaster is not synchronous.
$buildables = id(new HarbormasterBuildableQuery())
->setViewer($viewer)
->withContainerPHIDs(array($this->getPHID()))
->withBuildablePHIDs(array($diff->getPHID()))
->withManualBuildables(false)
->execute();

View file

@ -5,7 +5,7 @@ final class DifferentialHunkTestCase extends PhutilTestCase {
public function testMakeChanges() {
$root = dirname(__FILE__).'/hunk/';
$hunk = new DifferentialModernHunk();
$hunk = new DifferentialHunk();
$hunk->setChanges(Filesystem::readFile($root.'basic.diff'));
$hunk->setOldOffset(1);
$hunk->setNewOffset(11);
@ -23,7 +23,7 @@ final class DifferentialHunkTestCase extends PhutilTestCase {
);
$this->assertEqual($added, $hunk->getAddedLines());
$hunk = new DifferentialModernHunk();
$hunk = new DifferentialHunk();
$hunk->setChanges(Filesystem::readFile($root.'newline.diff'));
$hunk->setOldOffset(1);
$hunk->setNewOffset(11);

View file

@ -57,8 +57,19 @@ final class DifferentialRevisionPlanChangesTransaction
protected function validateAction($object, PhabricatorUser $viewer) {
if ($object->isDraft()) {
throw new Exception(
pht('You can not plan changes to a draft revision.'));
// See PHI346. Until the "Draft" state fully unprototypes, allow drafts
// to be moved to "changes planned" via the API. This preserves the
// behavior of "arc diff --plan-changes". We still prevent this
// transition from the web UI.
// TODO: Remove this once drafts leave prototype.
$editor = $this->getEditor();
$type_web = PhabricatorWebContentSource::SOURCECONST;
if ($editor->getContentSource()->getSource() == $type_web) {
throw new Exception(
pht('You can not plan changes to a draft revision.'));
}
}
if ($object->isChangePlanned()) {

View file

@ -0,0 +1,82 @@
<?php
final class DiffusionDatasourceEngineExtension
extends PhabricatorDatasourceEngineExtension {
public function newQuickSearchDatasources() {
return array(
new DiffusionRepositoryDatasource(),
new DiffusionSymbolDatasource(),
);
}
public function newJumpURI($query) {
$viewer = $this->getViewer();
// Send "r" to Diffusion.
if (preg_match('/^r\z/i', $query)) {
return '/diffusion/';
}
// Send "a" to the commit list ("Audit").
if (preg_match('/^a\z/i', $query)) {
return '/diffusion/commit/';
}
// Send "r <string>" to a search for a matching repository.
$matches = null;
if (preg_match('/^r\s+(.+)\z/i', $query, $matches)) {
$raw_query = $matches[1];
$engine = id(new PhabricatorRepository())
->newFerretEngine();
$compiler = id(new PhutilSearchQueryCompiler())
->setEnableFunctions(true);
$raw_tokens = $compiler->newTokens($raw_query);
$fulltext_tokens = array();
foreach ($raw_tokens as $raw_token) {
$fulltext_token = id(new PhabricatorFulltextToken())
->setToken($raw_token);
$fulltext_tokens[] = $fulltext_token;
}
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($viewer)
->withFerretConstraint($engine, $fulltext_tokens)
->execute();
if (count($repositories) == 1) {
// Just one match, jump to repository.
return head($repositories)->getURI();
} else {
// More than one match, jump to search.
return urisprintf(
'/diffusion/?order=relevance&query=%s#R',
$raw_query);
}
}
// Send "s <string>" to a symbol search.
$matches = null;
if (preg_match('/^s\s+(.+)\z/i', $query, $matches)) {
$symbol = $matches[1];
$parts = null;
if (preg_match('/(.*)(?:\\.|::|->)(.*)/', $symbol, $parts)) {
return urisprintf(
'/diffusion/symbol/%s/?jump=true&context=%s',
$parts[2],
$parts[1]);
} else {
return urisprintf(
'/diffusion/symbol/%s/?jump=true',
$symbol);
}
}
return null;
}
}

View file

@ -1,12 +0,0 @@
<?php
final class DiffusionQuickSearchEngineExtension
extends PhabricatorQuickSearchEngineExtension {
public function newQuickSearchDatasources() {
return array(
new DiffusionRepositoryDatasource(),
new DiffusionSymbolDatasource(),
);
}
}

View file

@ -0,0 +1,29 @@
<?php
final class DiffusionPreCommitContentPackageHeraldField
extends DiffusionPreCommitContentHeraldField {
const FIELDCONST = 'diffusion.pre.content.package';
public function getHeraldFieldName() {
return pht('Affected packages');
}
public function getFieldGroupKey() {
return HeraldRelatedFieldGroup::FIELDGROUPKEY;
}
public function getHeraldFieldValue($object) {
$packages = $this->getAdapter()->loadAffectedPackages();
return mpull($packages, 'getPHID');
}
protected function getHeraldFieldStandardType() {
return self::STANDARD_PHID_LIST;
}
protected function getDatasource() {
return new PhabricatorOwnersPackageDatasource();
}
}

View file

@ -0,0 +1,34 @@
<?php
final class DiffusionPreCommitContentPackageOwnerHeraldField
extends DiffusionPreCommitContentHeraldField {
const FIELDCONST = 'diffusion.pre.content.package.owners';
public function getHeraldFieldName() {
return pht('Affected package owners');
}
public function getFieldGroupKey() {
return HeraldRelatedFieldGroup::FIELDGROUPKEY;
}
public function getHeraldFieldValue($object) {
$packages = $this->getAdapter()->loadAffectedPackages();
if (!$packages) {
return array();
}
$owners = PhabricatorOwnersOwner::loadAllForPackages($packages);
return mpull($owners, 'getUserPHID');
}
protected function getHeraldFieldStandardType() {
return self::STANDARD_PHID_LIST;
}
protected function getDatasource() {
return new PhabricatorProjectOrUserDatasource();
}
}

View file

@ -87,4 +87,8 @@ abstract class HeraldPreCommitAdapter extends HeraldAdapter {
$this->hookEngine->getRepository()->getProjectPHIDs());
}
public function supportsWebhooks() {
return false;
}
}

View file

@ -7,6 +7,8 @@ final class HeraldPreCommitContentAdapter extends HeraldPreCommitAdapter {
private $fields;
private $revision = false;
private $affectedPackages;
public function getAdapterContentName() {
return pht('Commit Hook: Commit Content');
}
@ -223,4 +225,16 @@ final class HeraldPreCommitContentAdapter extends HeraldPreCommitAdapter {
$this->getObject()->getRefNew());
}
public function loadAffectedPackages() {
if ($this->affectedPackages === null) {
$packages = PhabricatorOwnersPackage::loadAffectedPackages(
$this->getHookEngine()->getRepository(),
$this->getDiffContent('name'));
$this->affectedPackages = $packages;
}
return $this->affectedPackages;
}
}

View file

@ -205,12 +205,11 @@ abstract class DiffusionView extends AphrontView {
final protected function renderBuildable(
HarbormasterBuildable $buildable,
$type = null) {
$status = $buildable->getBuildableStatus();
Javelin::initBehavior('phabricator-tooltips');
$icon = HarbormasterBuildable::getBuildableStatusIcon($status);
$color = HarbormasterBuildable::getBuildableStatusColor($status);
$name = HarbormasterBuildable::getBuildableStatusName($status);
$icon = $buildable->getStatusIcon();
$color = $buildable->getStatusColor();
$name = $buildable->getStatusDisplayName();
if ($type == 'button') {
return id(new PHUIButtonView())

View file

@ -80,20 +80,17 @@ final class PhabricatorVersionedDraft extends PhabricatorDraftDAO {
public static function purgeDrafts(
$object_phid,
$viewer_phid,
$version) {
$viewer_phid) {
$draft = new PhabricatorVersionedDraft();
$conn_w = $draft->establishConnection('w');
queryfx(
$conn_w,
'DELETE FROM %T WHERE objectPHID = %s AND authorPHID = %s
AND version <= %d',
'DELETE FROM %T WHERE objectPHID = %s AND authorPHID = %s',
$draft->getTableName(),
$object_phid,
$viewer_phid,
$version);
$viewer_phid);
}
}

View file

@ -396,16 +396,20 @@ abstract class DrydockBlueprintImplementation extends Phobject {
}
// For reasonable limits, actually check for an available slot.
$locks = DrydockSlotLock::loadLocks($blueprint_phid);
$locks = mpull($locks, null, 'getLockKey');
$slots = range(0, $limit - 1);
shuffle($slots);
$lock_names = array();
foreach ($slots as $slot) {
$slot_lock = "allocator({$blueprint_phid}).limit({$slot})";
if (empty($locks[$slot_lock])) {
return $slot_lock;
$lock_names[] = "allocator({$blueprint_phid}).limit({$slot})";
}
$locks = DrydockSlotLock::loadHeldLocks($lock_names);
$locks = mpull($locks, null, 'getLockKey');
foreach ($lock_names as $lock_name) {
if (empty($locks[$lock_name])) {
return $lock_name;
}
}
@ -414,7 +418,8 @@ abstract class DrydockBlueprintImplementation extends Phobject {
// lock will be free by the time we try to take it, but usually we'll just
// fail to grab the lock, throw an appropriate lock exception, and get back
// on the right path to retry later.
return $slot_lock;
return $lock_name;
}

View file

@ -206,7 +206,7 @@ final class DrydockWorkingCopyBlueprintImplementation
}
// Destroy the lease on the host.
$lease->releaseOnDestruction();
$lease->setReleaseOnDestruction(true);
if ($lease->isActive()) {
// Destroy the working copy on disk.

View file

@ -1,3 +0,0 @@
<?php
abstract class DrydockConstants extends Phobject {}

View file

@ -1,6 +1,7 @@
<?php
final class DrydockLeaseStatus extends DrydockConstants {
final class DrydockLeaseStatus
extends PhabricatorObjectStatus {
const STATUS_PENDING = 'pending';
const STATUS_ACQUIRED = 'acquired';
@ -9,24 +10,105 @@ final class DrydockLeaseStatus extends DrydockConstants {
const STATUS_BROKEN = 'broken';
const STATUS_DESTROYED = 'destroyed';
public static function newStatusObject($key) {
return new self($key, id(new self())->getStatusSpecification($key));
}
public static function getStatusMap() {
return array(
self::STATUS_PENDING => pht('Pending'),
self::STATUS_ACQUIRED => pht('Acquired'),
self::STATUS_ACTIVE => pht('Active'),
self::STATUS_RELEASED => pht('Released'),
self::STATUS_BROKEN => pht('Broken'),
self::STATUS_DESTROYED => pht('Destroyed'),
);
$map = id(new self())->getStatusSpecifications();
return ipull($map, 'name', 'key');
}
public static function getNameForStatus($status) {
$map = self::getStatusMap();
return idx($map, $status, pht('Unknown'));
$map = id(new self())->getStatusSpecification($status);
return $map['name'];
}
public static function getAllStatuses() {
return array_keys(self::getStatusMap());
return array_keys(id(new self())->getStatusSpecifications());
}
public function isActivating() {
return $this->getStatusProperty('isActivating');
}
public function isActive() {
return ($this->getKey() === self::STATUS_ACTIVE);
}
public function canRelease() {
return $this->getStatusProperty('isReleasable');
}
public function canReceiveCommands() {
return $this->getStatusProperty('isCommandable');
}
protected function newStatusSpecifications() {
return array(
array(
'key' => self::STATUS_PENDING,
'name' => pht('Pending'),
'icon' => 'fa-clock-o',
'color' => 'blue',
'isReleasable' => true,
'isCommandable' => true,
'isActivating' => true,
),
array(
'key' => self::STATUS_ACQUIRED,
'name' => pht('Acquired'),
'icon' => 'fa-refresh',
'color' => 'blue',
'isReleasable' => true,
'isCommandable' => true,
'isActivating' => true,
),
array(
'key' => self::STATUS_ACTIVE,
'name' => pht('Active'),
'icon' => 'fa-check',
'color' => 'green',
'isReleasable' => true,
'isCommandable' => true,
'isActivating' => false,
),
array(
'key' => self::STATUS_RELEASED,
'name' => pht('Released'),
'icon' => 'fa-circle-o',
'color' => 'blue',
'isReleasable' => false,
'isCommandable' => false,
'isActivating' => false,
),
array(
'key' => self::STATUS_BROKEN,
'name' => pht('Broken'),
'icon' => 'fa-times',
'color' => 'indigo',
'isReleasable' => true,
'isCommandable' => true,
'isActivating' => false,
),
array(
'key' => self::STATUS_DESTROYED,
'name' => pht('Destroyed'),
'icon' => 'fa-times',
'color' => 'grey',
'isReleasable' => false,
'isCommandable' => false,
'isActivating' => false,
),
);
}
protected function newUnknownStatusSpecification($status) {
return array(
'isReleasable' => false,
'isCommandable' => false,
'isActivating' => false,
);
}
}

View file

@ -1,6 +1,7 @@
<?php
final class DrydockResourceStatus extends DrydockConstants {
final class DrydockResourceStatus
extends PhabricatorObjectStatus {
const STATUS_PENDING = 'pending';
const STATUS_ACTIVE = 'active';
@ -8,23 +9,86 @@ final class DrydockResourceStatus extends DrydockConstants {
const STATUS_BROKEN = 'broken';
const STATUS_DESTROYED = 'destroyed';
public static function newStatusObject($key) {
return new self($key, id(new self())->getStatusSpecification($key));
}
public static function getStatusMap() {
return array(
self::STATUS_PENDING => pht('Pending'),
self::STATUS_ACTIVE => pht('Active'),
self::STATUS_RELEASED => pht('Released'),
self::STATUS_BROKEN => pht('Broken'),
self::STATUS_DESTROYED => pht('Destroyed'),
);
$map = id(new self())->getStatusSpecifications();
return ipull($map, 'name', 'key');
}
public static function getNameForStatus($status) {
$map = self::getStatusMap();
return idx($map, $status, pht('Unknown'));
$map = id(new self())->getStatusSpecification($status);
return $map['name'];
}
public static function getAllStatuses() {
return array_keys(self::getStatusMap());
return array_keys(id(new self())->getStatusSpecifications());
}
public function isActive() {
return ($this->getKey() === self::STATUS_ACTIVE);
}
public function canRelease() {
return $this->getStatusProperty('isReleasable');
}
public function canReceiveCommands() {
return $this->getStatusProperty('isCommandable');
}
protected function newStatusSpecifications() {
return array(
array(
'key' => self::STATUS_PENDING,
'name' => pht('Pending'),
'icon' => 'fa-clock-o',
'color' => 'blue',
'isReleasable' => true,
'isCommandable' => true,
),
array(
'key' => self::STATUS_ACTIVE,
'name' => pht('Active'),
'icon' => 'fa-check',
'color' => 'green',
'isReleasable' => true,
'isCommandable' => true,
),
array(
'key' => self::STATUS_RELEASED,
'name' => pht('Released'),
'icon' => 'fa-circle-o',
'color' => 'blue',
'isReleasable' => false,
'isCommandable' => false,
),
array(
'key' => self::STATUS_BROKEN,
'name' => pht('Broken'),
'icon' => 'fa-times',
'color' => 'indigo',
'isReleasable' => true,
'isCommandable' => false,
),
array(
'key' => self::STATUS_DESTROYED,
'name' => pht('Destroyed'),
'icon' => 'fa-times',
'color' => 'grey',
'isReleasable' => false,
'isCommandable' => false,
),
);
}
protected function newUnknownStatusSpecification($status) {
return array(
'isReleasable' => false,
'isCommandable' => false,
);
}
}

View file

@ -22,10 +22,19 @@ final class DrydockLeaseViewController extends DrydockLeaseController {
$header = id(new PHUIHeaderView())
->setHeader($title)
->setHeaderIcon('fa-link');
->setHeaderIcon('fa-link')
->setStatus(
$lease->getStatusIcon(),
$lease->getStatusColor(),
$lease->getStatusDisplayName());
if ($lease->isReleasing()) {
$header->setStatus('fa-exclamation-triangle', 'red', pht('Releasing'));
$header->addTag(
id(new PHUITagView())
->setType(PHUITagView::TYPE_SHADE)
->setIcon('fa-exclamation-triangle')
->setColor('red')
->setName('Releasing'));
}
$curtain = $this->buildCurtain($lease);
@ -118,10 +127,6 @@ final class DrydockLeaseViewController extends DrydockLeaseController {
$view = new PHUIPropertyListView();
$view->addProperty(
pht('Status'),
DrydockLeaseStatus::getNameForStatus($lease->getStatus()));
$view->addProperty(
pht('Resource Type'),
$lease->getResourceType());

View file

@ -24,10 +24,19 @@ final class DrydockResourceViewController extends DrydockResourceController {
->setUser($viewer)
->setPolicyObject($resource)
->setHeader($title)
->setHeaderIcon('fa-map');
->setHeaderIcon('fa-map')
->setStatus(
$resource->getStatusIcon(),
$resource->getStatusColor(),
$resource->getStatusDisplayName());
if ($resource->isReleasing()) {
$header->setStatus('fa-exclamation-triangle', 'red', pht('Releasing'));
$header->addTag(
id(new PHUITagView())
->setType(PHUITagView::TYPE_SHADE)
->setIcon('fa-exclamation-triangle')
->setColor('red')
->setName('Releasing'));
}
$curtain = $this->buildCurtain($resource);
@ -127,12 +136,6 @@ final class DrydockResourceViewController extends DrydockResourceController {
$viewer = $this->getViewer();
$view = new PHUIPropertyListView();
$status = $resource->getStatus();
$status = DrydockResourceStatus::getNameForStatus($status);
$view->addProperty(
pht('Status'),
$status);
$until = $resource->getUntil();
if ($until) {

View file

@ -0,0 +1,4 @@
<?php
final class DrydockAcquiredBrokenResourceException
extends Exception {}

View file

@ -0,0 +1,4 @@
<?php
final class DrydockResourceLockException
extends Exception {}

View file

@ -0,0 +1,26 @@
<?php
final class DrydockLeaseAllocationFailureLogType extends DrydockLogType {
const LOGCONST = 'core.lease.allocation-failure';
public function getLogTypeName() {
return pht('Allocation Failed');
}
public function getLogTypeIcon(array $data) {
return 'fa-times red';
}
public function renderLog(array $data) {
$class = idx($data, 'class');
$message = idx($data, 'message');
return pht(
'One or more blueprints promised a new resource, but failed when '.
'allocating: [%s] %s',
$class,
$message);
}
}

View file

@ -13,14 +13,13 @@ final class DrydockLeaseNoAuthorizationsLogType extends DrydockLogType {
}
public function renderLog(array $data) {
$viewer = $this->getViewer();
$authorizing_phid = idx($data, 'authorizingPHID');
return pht(
'The object which authorized this lease (%s) is not authorized to use '.
'any of the blueprints the lease lists. Approve the authorizations '.
'before using the lease.',
$viewer->renderHandle($authorizing_phid)->render());
$this->renderHandle($authorizing_phid));
}
}

View file

@ -0,0 +1,26 @@
<?php
final class DrydockLeaseReacquireLogType extends DrydockLogType {
const LOGCONST = 'core.lease.reacquire';
public function getLogTypeName() {
return pht('Reacquiring Resource');
}
public function getLogTypeIcon(array $data) {
return 'fa-refresh yellow';
}
public function renderLog(array $data) {
$class = idx($data, 'class');
$message = idx($data, 'message');
return pht(
'Lease acquired a resource but failed to activate; acquisition '.
'will be retried: [%s] %s',
$class,
$message);
}
}

View file

@ -13,13 +13,11 @@ final class DrydockLeaseReclaimLogType extends DrydockLogType {
}
public function renderLog(array $data) {
$viewer = $this->getViewer();
$resource_phids = idx($data, 'resourcePHIDs', array());
return pht(
'Reclaimed resource %s.',
$viewer->renderHandleList($resource_phids)->render());
$this->renderHandleList($resource_phids));
}
}

View file

@ -13,13 +13,11 @@ final class DrydockLeaseWaitingForResourcesLogType extends DrydockLogType {
}
public function renderLog(array $data) {
$viewer = $this->getViewer();
$blueprint_phids = idx($data, 'blueprintPHIDs', array());
return pht(
'Waiting for available resources from: %s.',
$viewer->renderHandleList($blueprint_phids)->render());
$this->renderHandleList($blueprint_phids));
}
}

View file

@ -4,17 +4,18 @@ abstract class DrydockLogType extends Phobject {
private $viewer;
private $log;
private $renderingMode = 'text';
abstract public function getLogTypeName();
abstract public function getLogTypeIcon(array $data);
abstract public function renderLog(array $data);
public function setViewer(PhabricatorUser $viewer) {
final public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;
}
public function getViewer() {
final public function getViewer() {
return $this->viewer;
}
@ -38,4 +39,36 @@ abstract class DrydockLogType extends Phobject {
->execute();
}
final public function renderLogForText($data) {
$this->renderingMode = 'text';
return $this->renderLog($data);
}
final public function renderLogForHTML($data) {
$this->renderingMode = 'html';
return $this->renderLog($data);
}
final protected function renderHandle($phid) {
$viewer = $this->getViewer();
$handle = $viewer->renderHandle($phid);
if ($this->renderingMode == 'html') {
return $handle->render();
} else {
return $handle->setAsText(true)->render();
}
}
final protected function renderHandleList(array $phids) {
$viewer = $this->getViewer();
$handle_list = $viewer->renderHandleList($phids);
if ($this->renderingMode == 'html') {
return $handle_list->render();
} else {
return $handle_list->setAsText(true)->render();
}
}
}

View file

@ -0,0 +1,26 @@
<?php
final class DrydockResourceAllocationFailureLogType extends DrydockLogType {
const LOGCONST = 'core.resource.allocation-failure';
public function getLogTypeName() {
return pht('Allocation Failed');
}
public function getLogTypeIcon(array $data) {
return 'fa-times red';
}
public function renderLog(array $data) {
$class = idx($data, 'class');
$message = idx($data, 'message');
return pht(
'Blueprint failed to allocate a resource after claiming it would '.
'be able to: [%s] %s',
$class,
$message);
}
}

View file

@ -13,12 +13,11 @@ final class DrydockResourceReclaimLogType extends DrydockLogType {
}
public function renderLog(array $data) {
$viewer = $this->getViewer();
$reclaimer_phid = idx($data, 'reclaimerPHID');
return pht(
'Resource reclaimed by %s.',
$viewer->renderHandle($reclaimer_phid)->render());
$this->renderHandle($reclaimer_phid));
}
}

View file

@ -62,6 +62,10 @@ final class DrydockManagementLeaseWorkflow
$drydock_phid = id(new PhabricatorDrydockApplication())->getPHID();
$lease->setAuthorizingPHID($drydock_phid);
if ($attributes) {
$lease->setAttributes($attributes);
}
// TODO: This is not hugely scalable, although this is a debugging workflow
// so maybe it's fine. Do we even need `bin/drydock lease` in the long run?
$all_blueprints = id(new DrydockBlueprintQuery())
@ -76,27 +80,129 @@ final class DrydockManagementLeaseWorkflow
}
$lease->setAllowedBlueprintPHIDs($allowed_phids);
if ($attributes) {
$lease->setAttributes($attributes);
}
if ($until) {
$lease->setUntil($until);
}
// If something fatals or the user interrupts the process (for example,
// with "^C"), release the lease. We'll cancel this below, if the lease
// actually activates.
$lease->setReleaseOnDestruction(true);
// TODO: This would probably be better handled with PhutilSignalRouter,
// but it currently doesn't route SIGINT. We're initializing it to setup
// SIGTERM handling and make eventual migration easier.
$router = PhutilSignalRouter::getRouter();
pcntl_signal(SIGINT, array($this, 'didReceiveInterrupt'));
$t_start = microtime(true);
$lease->queueForActivation();
echo tsprintf(
"%s\n",
"%s\n\n __%s__\n\n%s\n",
pht('Queued lease for activation:'),
PhabricatorEnv::getProductionURI($lease->getURI()),
pht('Waiting for daemons to activate lease...'));
$lease->waitUntilActive();
$this->waitUntilActive($lease);
// Now that we've survived activation and the lease is good, make it
// durable.
$lease->setReleaseOnDestruction(false);
$t_end = microtime(true);
echo tsprintf(
"%s\n",
pht('Activated lease "%s".', $lease->getID()));
"%s\n\n %s\n\n%s\n",
pht(
'Activation complete. This lease is permanent until manually '.
'released with:'),
pht('$ ./bin/drydock release-lease --id %d', $lease->getID()),
pht(
'Lease activated in %sms.',
new PhutilNumber((int)(($t_end - $t_start) * 1000))));
return 0;
}
public function didReceiveInterrupt($signo) {
// Doing this makes us run destructors, particularly the "release on
// destruction" trigger on the lease.
exit(128 + $signo);
}
private function waitUntilActive(DrydockLease $lease) {
$viewer = $this->getViewer();
$log_cursor = 0;
$log_types = DrydockLogType::getAllLogTypes();
$is_active = false;
while (!$is_active) {
$lease->reload();
// While we're waiting, show the user any logs which the daemons have
// generated to give them some clue about what's going on.
$logs = id(new DrydockLogQuery())
->setViewer($viewer)
->withLeasePHIDs(array($lease->getPHID()))
->setBeforeID($log_cursor)
->execute();
if ($logs) {
$logs = mpull($logs, null, 'getID');
ksort($logs);
$log_cursor = last_key($logs);
}
foreach ($logs as $log) {
$type_key = $log->getType();
if (isset($log_types[$type_key])) {
$type_object = id(clone $log_types[$type_key])
->setLog($log)
->setViewer($viewer);
$log_data = $log->getData();
$type = $type_object->getLogTypeName();
$data = $type_object->renderLogForText($log_data);
} else {
$type = pht('Unknown ("%s")', $type_key);
$data = null;
}
echo tsprintf(
"<%s> %B\n",
$type,
$data);
}
$status = $lease->getStatus();
switch ($status) {
case DrydockLeaseStatus::STATUS_ACTIVE:
$is_active = true;
break;
case DrydockLeaseStatus::STATUS_RELEASED:
throw new Exception(pht('Lease has already been released!'));
case DrydockLeaseStatus::STATUS_DESTROYED:
throw new Exception(pht('Lease has already been destroyed!'));
case DrydockLeaseStatus::STATUS_BROKEN:
throw new Exception(pht('Lease has been broken!'));
case DrydockLeaseStatus::STATUS_PENDING:
case DrydockLeaseStatus::STATUS_ACQUIRED:
break;
default:
throw new Exception(
pht(
'Lease has unknown status "%s".',
$status));
}
if ($is_active) {
break;
} else {
sleep(1);
}
}
}
}

View file

@ -36,8 +36,8 @@ final class DrydockLease extends DrydockDAO
* a lease, as you don't need to explicitly handle exceptions to properly
* release the lease.
*/
public function releaseOnDestruction() {
$this->releaseOnDestruction = true;
public function setReleaseOnDestruction($release) {
$this->releaseOnDestruction = $release;
return $this;
}
@ -175,57 +175,6 @@ final class DrydockLease extends DrydockDAO
return $this;
}
public function isActivating() {
switch ($this->getStatus()) {
case DrydockLeaseStatus::STATUS_PENDING:
case DrydockLeaseStatus::STATUS_ACQUIRED:
return true;
}
return false;
}
public function isActive() {
switch ($this->getStatus()) {
case DrydockLeaseStatus::STATUS_ACTIVE:
return true;
}
return false;
}
public function waitUntilActive() {
while (true) {
$lease = $this->reload();
if (!$lease) {
throw new Exception(pht('Failed to reload lease.'));
}
$status = $lease->getStatus();
switch ($status) {
case DrydockLeaseStatus::STATUS_ACTIVE:
return;
case DrydockLeaseStatus::STATUS_RELEASED:
throw new Exception(pht('Lease has already been released!'));
case DrydockLeaseStatus::STATUS_DESTROYED:
throw new Exception(pht('Lease has already been destroyed!'));
case DrydockLeaseStatus::STATUS_BROKEN:
throw new Exception(pht('Lease has been broken!'));
case DrydockLeaseStatus::STATUS_PENDING:
case DrydockLeaseStatus::STATUS_ACQUIRED:
break;
default:
throw new Exception(
pht(
'Lease has unknown status "%s".',
$status));
}
sleep(1);
}
}
public function setActivateWhenAcquired($activate) {
$this->activateWhenAcquired = true;
return $this;
@ -264,30 +213,75 @@ final class DrydockLease extends DrydockDAO
}
}
$this->openTransaction();
// Before we associate the lease with the resource, we lock the resource
// and reload it to make sure it is still pending or active. If we don't
// do this, the resource may have just been reclaimed. (Once we acquire
// the resource that stops it from being released, so we're nearly safe.)
$resource_phid = $resource->getPHID();
$hash = PhabricatorHash::digestForIndex($resource_phid);
$lock_key = 'drydock.resource:'.$hash;
$lock = PhabricatorGlobalLock::newLock($lock_key);
try {
DrydockSlotLock::acquireLocks($this->getPHID(), $this->slotLocks);
$this->slotLocks = array();
} catch (DrydockSlotLockException $ex) {
$this->killTransaction();
$this->logEvent(
DrydockSlotLockFailureLogType::LOGCONST,
array(
'locks' => $ex->getLockMap(),
));
throw $ex;
$lock->lock(15);
} catch (Exception $ex) {
throw new DrydockResourceLockException(
pht(
'Failed to acquire lock for resource ("%s") while trying to '.
'acquire lease ("%s").',
$resource->getPHID(),
$this->getPHID()));
}
$this
->setResourcePHID($resource->getPHID())
->attachResource($resource)
->setStatus($new_status)
->save();
$resource->reload();
$this->saveTransaction();
if (($resource->getStatus() !== DrydockResourceStatus::STATUS_ACTIVE) &&
($resource->getStatus() !== DrydockResourceStatus::STATUS_PENDING)) {
throw new DrydockAcquiredBrokenResourceException(
pht(
'Trying to acquire lease ("%s") on a resource ("%s") in the '.
'wrong status ("%s").',
$this->getPHID(),
$resource->getPHID(),
$resource->getStatus()));
}
$caught = null;
try {
$this->openTransaction();
try {
DrydockSlotLock::acquireLocks($this->getPHID(), $this->slotLocks);
$this->slotLocks = array();
} catch (DrydockSlotLockException $ex) {
$this->killTransaction();
$this->logEvent(
DrydockSlotLockFailureLogType::LOGCONST,
array(
'locks' => $ex->getLockMap(),
));
throw $ex;
}
$this
->setResourcePHID($resource->getPHID())
->attachResource($resource)
->setStatus($new_status)
->save();
$this->saveTransaction();
} catch (Exception $ex) {
$caught = $ex;
}
$lock->unlock();
if ($caught) {
throw $caught;
}
$this->isAcquired = true;
@ -357,30 +351,6 @@ final class DrydockLease extends DrydockDAO
return $this->isActivated;
}
public function canRelease() {
if (!$this->getID()) {
return false;
}
switch ($this->getStatus()) {
case DrydockLeaseStatus::STATUS_RELEASED:
case DrydockLeaseStatus::STATUS_DESTROYED:
return false;
default:
return true;
}
}
public function canReceiveCommands() {
switch ($this->getStatus()) {
case DrydockLeaseStatus::STATUS_RELEASED:
case DrydockLeaseStatus::STATUS_DESTROYED:
return false;
default:
return true;
}
}
public function scheduleUpdate($epoch = null) {
PhabricatorWorker::scheduleTask(
'DrydockLeaseUpdateWorker',
@ -468,6 +438,51 @@ final class DrydockLease extends DrydockDAO
return $this;
}
public function getURI() {
$id = $this->getID();
return "/drydock/lease/{$id}/";
}
/* -( Status )------------------------------------------------------------- */
public function getStatusObject() {
return DrydockLeaseStatus::newStatusObject($this->getStatus());
}
public function getStatusIcon() {
return $this->getStatusObject()->getIcon();
}
public function getStatusColor() {
return $this->getStatusObject()->getColor();
}
public function getStatusDisplayName() {
return $this->getStatusObject()->getDisplayName();
}
public function isActivating() {
return $this->getStatusObject()->isActivating();
}
public function isActive() {
return $this->getStatusObject()->isActive();
}
public function canRelease() {
if (!$this->getID()) {
return false;
}
return $this->getStatusObject()->canRelease();
}
public function canReceiveCommands() {
return $this->getStatusObject()->canReceiveCommands();
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -235,16 +235,6 @@ final class DrydockResource extends DrydockDAO
return $this->isActivated;
}
public function canRelease() {
switch ($this->getStatus()) {
case DrydockResourceStatus::STATUS_RELEASED:
case DrydockResourceStatus::STATUS_DESTROYED:
return false;
default:
return true;
}
}
public function scheduleUpdate($epoch = null) {
PhabricatorWorker::scheduleTask(
'DrydockResourceUpdateWorker',
@ -282,26 +272,6 @@ final class DrydockResource extends DrydockDAO
}
}
public function canReceiveCommands() {
switch ($this->getStatus()) {
case DrydockResourceStatus::STATUS_RELEASED:
case DrydockResourceStatus::STATUS_BROKEN:
case DrydockResourceStatus::STATUS_DESTROYED:
return false;
default:
return true;
}
}
public function isActive() {
switch ($this->getStatus()) {
case DrydockResourceStatus::STATUS_ACTIVE:
return true;
}
return false;
}
public function logEvent($type, array $data = array()) {
$log = id(new DrydockLog())
->setEpoch(PhabricatorTime::getNow())
@ -315,6 +285,38 @@ final class DrydockResource extends DrydockDAO
}
/* -( Status )------------------------------------------------------------- */
public function getStatusObject() {
return DrydockResourceStatus::newStatusObject($this->getStatus());
}
public function getStatusIcon() {
return $this->getStatusObject()->getIcon();
}
public function getStatusColor() {
return $this->getStatusObject()->getColor();
}
public function getStatusDisplayName() {
return $this->getStatusObject()->getDisplayName();
}
public function canRelease() {
return $this->getStatusObject()->canRelease();
}
public function canReceiveCommands() {
return $this->getStatusObject()->canReceiveCommands();
}
public function isActive() {
return $this->getStatusObject()->isActive();
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -26,20 +26,20 @@ final class DrydockLeaseListView extends AphrontView {
if ($resource_phid) {
$item->addAttribute(
$viewer->renderHandle($resource_phid));
} else {
$item->addAttribute(
pht(
'Resource: %s',
$lease->getResourceType()));
}
$status = DrydockLeaseStatus::getNameForStatus($lease->getStatus());
$item->addAttribute($status);
$item->setEpoch($lease->getDateCreated());
// TODO: Tailor this for clarity.
if ($lease->isActivating()) {
$item->setStatusIcon('fa-dot-circle-o yellow');
} else if ($lease->isActive()) {
$item->setStatusIcon('fa-dot-circle-o green');
} else {
$item->setStatusIcon('fa-dot-circle-o red');
}
$icon = $lease->getStatusIcon();
$color = $lease->getStatusColor();
$label = $lease->getStatusDisplayName();
$item->setStatusIcon("{$icon} {$color}", $label);
$view->addItem($item);
}

View file

@ -52,7 +52,8 @@ final class DrydockLogListView extends AphrontView {
$type = $type_object->getLogTypeName();
$icon = $type_object->getLogTypeIcon($log_data);
$data = $type_object->renderLog($log_data);
$data = $type_object->renderLogForHTML($log_data);
$data = phutil_escape_html_newlines($data);
} else {
$type = pht('<Unknown: %s>', $type_key);
$data = null;

View file

@ -23,23 +23,11 @@ final class DrydockResourceListView extends AphrontView {
->setObjectName(pht('Resource %d', $id))
->setHeader($resource->getResourceName());
$status = DrydockResourceStatus::getNameForStatus($resource->getStatus());
$item->addAttribute($status);
$icon = $resource->getStatusIcon();
$color = $resource->getStatusColor();
$label = $resource->getStatusDisplayName();
switch ($resource->getStatus()) {
case DrydockResourceStatus::STATUS_PENDING:
$item->setStatusIcon('fa-dot-circle-o yellow');
break;
case DrydockResourceStatus::STATUS_ACTIVE:
$item->setStatusIcon('fa-dot-circle-o green');
break;
case DrydockResourceStatus::STATUS_DESTROYED:
$item->setStatusIcon('fa-times-circle-o black');
break;
default:
$item->setStatusIcon('fa-dot-circle-o red');
break;
}
$item->setStatusIcon("{$icon} {$color}", $label);
$view->addItem($item);
}

View file

@ -43,6 +43,27 @@ final class DrydockLeaseUpdateWorker extends DrydockWorker {
private function handleUpdate(DrydockLease $lease) {
try {
$this->updateLease($lease);
} catch (DrydockAcquiredBrokenResourceException $ex) {
// If this lease acquired a resource but failed to activate, we don't
// need to break the lease. We can throw it back in the pool and let
// it take another shot at acquiring a new resource.
// Before we throw it back, release any locks the lease is holding.
DrydockSlotLock::releaseLocks($lease->getPHID());
$lease
->setStatus(DrydockLeaseStatus::STATUS_PENDING)
->setResourcePHID(null)
->save();
$lease->logEvent(
DrydockLeaseReacquireLogType::LOGCONST,
array(
'class' => get_class($ex),
'message' => $ex->getMessage(),
));
$this->yieldLease($lease, $ex);
} catch (Exception $ex) {
if ($this->isTemporaryException($ex)) {
$this->yieldLease($lease, $ex);
@ -216,17 +237,51 @@ final class DrydockLeaseUpdateWorker extends DrydockWorker {
// this.
break;
} catch (Exception $ex) {
// This failure is not normally expected, so log it. It can be
// caused by something mundane and recoverable, however (see below
// for discussion).
// We log to the blueprint separately from the log to the lease:
// the lease is not attached to a blueprint yet so the lease log
// will not show up on the blueprint; more than one blueprint may
// fail; and the lease is not really impacted (and won't log) if at
// least one blueprint actually works.
$blueprint->logEvent(
DrydockResourceAllocationFailureLogType::LOGCONST,
array(
'class' => get_class($ex),
'message' => $ex->getMessage(),
));
$exceptions[] = $ex;
}
}
if (!$resources) {
throw new PhutilAggregateException(
// If one or more blueprints claimed that they would be able to
// allocate resources but none are actually able to allocate resources,
// log the failure and yield so we try again soon.
// This can happen if some unexpected issue occurs during allocation
// (for example, a call to build a VM fails for some reason) or if we
// raced another allocator and the blueprint is now full.
$ex = new PhutilAggregateException(
pht(
'All blueprints failed to allocate a suitable new resource when '.
'trying to allocate lease "%s".',
'trying to allocate lease ("%s").',
$lease->getPHID()),
$exceptions);
$lease->logEvent(
DrydockLeaseAllocationFailureLogType::LOGCONST,
array(
'class' => get_class($ex),
'message' => $ex->getMessage(),
));
throw new PhabricatorWorkerYieldException(15);
}
$resources = $this->removeUnacquirableResources($resources, $lease);
@ -247,23 +302,38 @@ final class DrydockLeaseUpdateWorker extends DrydockWorker {
$resources = $this->rankResources($resources, $lease);
$exceptions = array();
$yields = array();
$allocated = false;
foreach ($resources as $resource) {
try {
$this->acquireLease($resource, $lease);
$allocated = true;
break;
} catch (DrydockResourceLockException $ex) {
// We need to lock the resource to actually acquire it. If we aren't
// able to acquire the lock quickly enough, we can yield and try again
// later.
$yields[] = $ex;
} catch (DrydockAcquiredBrokenResourceException $ex) {
// If a resource was reclaimed or destroyed by the time we actually
// got around to acquiring it, we just got unlucky. We can yield and
// try again later.
$yields[] = $ex;
} catch (Exception $ex) {
$exceptions[] = $ex;
}
}
if (!$allocated) {
throw new PhutilAggregateException(
pht(
'Unable to acquire lease "%s" on any resource.',
$lease->getPHID()),
$exceptions);
if ($yields) {
throw new PhabricatorWorkerYieldException(15);
} else {
throw new PhutilAggregateException(
pht(
'Unable to acquire lease "%s" on any resource.',
$lease->getPHID()),
$exceptions);
}
}
}
@ -715,9 +785,12 @@ final class DrydockLeaseUpdateWorker extends DrydockWorker {
}
if ($resource_status != DrydockResourceStatus::STATUS_ACTIVE) {
throw new Exception(
throw new DrydockAcquiredBrokenResourceException(
pht(
'Trying to activate lease on a dead resource (in status "%s").',
'Trying to activate lease ("%s") on a resource ("%s") in '.
'the wrong status ("%s").',
$lease->getPHID(),
$resource->getPHID(),
$resource_status));
}

View file

@ -62,7 +62,7 @@ final class DrydockRepositoryOperationUpdateWorker
DrydockCommandInterface::INTERFACE_TYPE);
// No matter what happens here, destroy the lease away once we're done.
$lease->releaseOnDestruction(true);
$lease->setReleaseOnDestruction(true);
$operation->applyOperation($interface);

View file

@ -65,7 +65,7 @@ final class HarbormasterQueryBuildablesConduitAPIMethod
$monogram = $buildable->getMonogram();
$status = $buildable->getBuildableStatus();
$status_name = HarbormasterBuildable::getBuildableStatusName($status);
$status_name = $buildable->getStatusDisplayName();
$data[] = array(
'id' => $buildable->getID(),

View file

@ -245,7 +245,7 @@ final class HarbormasterSendMessageConduitAPIMethod
}
$save[] = HarbormasterBuildMessage::initializeNewMessage($viewer)
->setBuildTargetPHID($build_target->getPHID())
->setReceiverPHID($build_target->getPHID())
->setType($message_type);
$build_target->openTransaction();

View file

@ -2,51 +2,56 @@
final class HarbormasterBuildStatus extends Phobject {
/**
* Not currently being built.
*/
const STATUS_INACTIVE = 'inactive';
/**
* Pending pick up by the Harbormaster daemon.
*/
const STATUS_PENDING = 'pending';
/**
* Current building the buildable.
*/
const STATUS_BUILDING = 'building';
/**
* The build has passed.
*/
const STATUS_PASSED = 'passed';
/**
* The build has failed.
*/
const STATUS_FAILED = 'failed';
/**
* The build has aborted.
*/
const STATUS_ABORTED = 'aborted';
/**
* The build encountered an unexpected error.
*/
const STATUS_ERROR = 'error';
/**
* The build has been paused.
*/
const STATUS_PAUSED = 'paused';
/**
* The build has been deadlocked.
*/
const STATUS_DEADLOCKED = 'deadlocked';
private $key;
private $properties;
public function __construct($key, array $properties) {
$this->key = $key;
$this->properties = $properties;
}
public static function newBuildStatusObject($status) {
$spec = self::getBuildStatusSpec($status);
return new self($status, $spec);
}
private function getProperty($key) {
if (!array_key_exists($key, $this->properties)) {
throw new Exception(
pht(
'Attempting to access unknown build status property ("%s").',
$key));
}
return $this->properties[$key];
}
public function isBuilding() {
return $this->getProperty('isBuilding');
}
public function isPaused() {
return ($this->key === self::STATUS_PAUSED);
}
public function isComplete() {
return $this->getProperty('isComplete');
}
public function isPassed() {
return ($this->key === self::STATUS_PASSED);
}
/**
* Get a human readable name for a build status constant.
@ -56,7 +61,7 @@ final class HarbormasterBuildStatus extends Phobject {
*/
public static function getBuildStatusName($status) {
$spec = self::getBuildStatusSpec($status);
return idx($spec, 'name', pht('Unknown ("%s")', $status));
return $spec['name'];
}
public static function getBuildStatusMap() {
@ -66,17 +71,17 @@ final class HarbormasterBuildStatus extends Phobject {
public static function getBuildStatusIcon($status) {
$spec = self::getBuildStatusSpec($status);
return idx($spec, 'icon', 'fa-question-circle');
return $spec['icon'];
}
public static function getBuildStatusColor($status) {
$spec = self::getBuildStatusSpec($status);
return idx($spec, 'color', 'bluegrey');
return $spec['color'];
}
public static function getBuildStatusANSIColor($status) {
$spec = self::getBuildStatusSpec($status);
return idx($spec, 'color.ansi', 'magenta');
return $spec['color.ansi'];
}
public static function getWaitingStatusConstants() {
@ -110,60 +115,90 @@ final class HarbormasterBuildStatus extends Phobject {
'icon' => 'fa-circle-o',
'color' => 'dark',
'color.ansi' => 'yellow',
'isBuilding' => false,
'isComplete' => false,
),
self::STATUS_PENDING => array(
'name' => pht('Pending'),
'icon' => 'fa-circle-o',
'color' => 'blue',
'color.ansi' => 'yellow',
'isBuilding' => true,
'isComplete' => false,
),
self::STATUS_BUILDING => array(
'name' => pht('Building'),
'icon' => 'fa-chevron-circle-right',
'color' => 'blue',
'color.ansi' => 'yellow',
'isBuilding' => true,
'isComplete' => false,
),
self::STATUS_PASSED => array(
'name' => pht('Passed'),
'icon' => 'fa-check-circle',
'color' => 'green',
'color.ansi' => 'green',
'isBuilding' => false,
'isComplete' => true,
),
self::STATUS_FAILED => array(
'name' => pht('Failed'),
'icon' => 'fa-times-circle',
'color' => 'red',
'color.ansi' => 'red',
'isBuilding' => false,
'isComplete' => true,
),
self::STATUS_ABORTED => array(
'name' => pht('Aborted'),
'icon' => 'fa-minus-circle',
'color' => 'red',
'color.ansi' => 'red',
'isBuilding' => false,
'isComplete' => true,
),
self::STATUS_ERROR => array(
'name' => pht('Unexpected Error'),
'icon' => 'fa-minus-circle',
'color' => 'red',
'color.ansi' => 'red',
'isBuilding' => false,
'isComplete' => true,
),
self::STATUS_PAUSED => array(
'name' => pht('Paused'),
'icon' => 'fa-minus-circle',
'color' => 'dark',
'color.ansi' => 'yellow',
'isBuilding' => false,
'isComplete' => false,
),
self::STATUS_DEADLOCKED => array(
'name' => pht('Deadlocked'),
'icon' => 'fa-exclamation-circle',
'color' => 'red',
'color.ansi' => 'red',
'isBuilding' => false,
'isComplete' => true,
),
);
}
private static function getBuildStatusSpec($status) {
return idx(self::getBuildStatusSpecMap(), $status, array());
$map = self::getBuildStatusSpecMap();
if (isset($map[$status])) {
return $map[$status];
}
return array(
'name' => pht('Unknown ("%s")', $status),
'icon' => 'fa-question-circle',
'color' => 'bluegrey',
'color.ansi' => 'magenta',
'isBuilding' => false,
'isComplete' => false,
);
}
}

View file

@ -0,0 +1,92 @@
<?php
final class HarbormasterBuildableStatus extends Phobject {
const STATUS_PREPARING = 'preparing';
const STATUS_BUILDING = 'building';
const STATUS_PASSED = 'passed';
const STATUS_FAILED = 'failed';
private $key;
private $properties;
public function __construct($key, array $properties) {
$this->key = $key;
$this->properties = $properties;
}
public static function newBuildableStatusObject($status) {
$spec = self::getSpecification($status);
return new self($status, $spec);
}
private function getProperty($key) {
if (!array_key_exists($key, $this->properties)) {
throw new Exception(
pht(
'Attempting to access unknown buildable status property ("%s").',
$key));
}
return $this->properties[$key];
}
public function getIcon() {
return $this->getProperty('icon');
}
public function getDisplayName() {
return $this->getProperty('name');
}
public function getColor() {
return $this->getProperty('color');
}
public function isPreparing() {
return ($this->key === self::STATUS_PREPARING);
}
public static function getOptionMap() {
return ipull(self::getSpecifications(), 'name');
}
private static function getSpecifications() {
return array(
self::STATUS_PREPARING => array(
'name' => pht('Preparing'),
'color' => 'blue',
'icon' => 'fa-hourglass-o',
),
self::STATUS_BUILDING => array(
'name' => pht('Building'),
'color' => 'blue',
'icon' => 'fa-chevron-circle-right',
),
self::STATUS_PASSED => array(
'name' => pht('Passed'),
'color' => 'green',
'icon' => 'fa-check-circle',
),
self::STATUS_FAILED => array(
'name' => pht('Failed'),
'color' => 'red',
'icon' => 'fa-times-circle',
),
);
}
private static function getSpecification($status) {
$map = self::getSpecifications();
if (isset($map[$status])) {
return $map[$status];
}
return array(
'name' => pht('Unknown ("%s")', $status),
'icon' => 'fa-question-circle',
'color' => 'bluegrey',
);
}
}

View file

@ -65,9 +65,9 @@ final class HarbormasterBuildViewController
if ($build_targets) {
$messages = id(new HarbormasterBuildMessageQuery())
->setViewer($viewer)
->withBuildTargetPHIDs(mpull($build_targets, 'getPHID'))
->withReceiverPHIDs(mpull($build_targets, 'getPHID'))
->execute();
$messages = mgroup($messages, 'getBuildTargetPHID');
$messages = mgroup($messages, 'getReceiverPHID');
} else {
$messages = array();
}

View file

@ -36,6 +36,10 @@ final class HarbormasterBuildableViewController
->setHeader($title)
->setUser($viewer)
->setPolicyObject($buildable)
->setStatus(
$buildable->getStatusIcon(),
$buildable->getStatusColor(),
$buildable->getStatusDisplayName())
->setHeaderIcon('fa-recycle');
$timeline = $this->buildTransactionTimeline(

View file

@ -59,6 +59,12 @@ final class HarbormasterPlanRunController extends HarbormasterPlanController {
if (!$errors) {
$buildable->save();
$buildable->sendMessage(
$viewer,
HarbormasterMessageType::BUILDABLE_BUILD,
false);
$buildable->applyPlan($plan, array(), $viewer->getPHID());
$buildable_uri = '/B'.$buildable->getID();

View file

@ -382,12 +382,12 @@ final class HarbormasterBuildEngine extends Phobject {
$messages = id(new HarbormasterBuildMessageQuery())
->setViewer($this->getViewer())
->withBuildTargetPHIDs(array_keys($waiting_targets))
->withReceiverPHIDs(array_keys($waiting_targets))
->withConsumed(false)
->execute();
foreach ($messages as $message) {
$target = $waiting_targets[$message->getBuildTargetPHID()];
$target = $waiting_targets[$message->getReceiverPHID()];
switch ($message->getType()) {
case HarbormasterMessageType::MESSAGE_PASS:
@ -428,7 +428,7 @@ final class HarbormasterBuildEngine extends Phobject {
* @param HarbormasterBuild The buildable to update.
* @return void
*/
private function updateBuildable(HarbormasterBuildable $buildable) {
public function updateBuildable(HarbormasterBuildable $buildable) {
$viewer = $this->getViewer();
$lock_key = 'harbormaster.buildable:'.$buildable->getID();
@ -440,39 +440,96 @@ final class HarbormasterBuildEngine extends Phobject {
->needBuilds(true)
->executeOne();
$all_pass = true;
$any_fail = false;
foreach ($buildable->getBuilds() as $build) {
if ($build->getBuildStatus() != HarbormasterBuildStatus::STATUS_PASSED) {
$all_pass = false;
}
if (in_array($build->getBuildStatus(), array(
HarbormasterBuildStatus::STATUS_FAILED,
HarbormasterBuildStatus::STATUS_ERROR,
HarbormasterBuildStatus::STATUS_DEADLOCKED,
))) {
$messages = id(new HarbormasterBuildMessageQuery())
->setViewer($viewer)
->withReceiverPHIDs(array($buildable->getPHID()))
->withConsumed(false)
->execute();
$any_fail = true;
$done_preparing = false;
$update_container = false;
foreach ($messages as $message) {
switch ($message->getType()) {
case HarbormasterMessageType::BUILDABLE_BUILD:
$done_preparing = true;
break;
case HarbormasterMessageType::BUILDABLE_CONTAINER:
$update_container = true;
break;
default:
break;
}
$message
->setIsConsumed(true)
->save();
}
// If we received a "build" command, all builds are scheduled and we can
// move out of "preparing" into "building".
if ($done_preparing) {
if ($buildable->isPreparing()) {
$buildable
->setBuildableStatus(HarbormasterBuildableStatus::STATUS_BUILDING)
->save();
}
}
if ($any_fail) {
$new_status = HarbormasterBuildable::STATUS_FAILED;
} else if ($all_pass) {
$new_status = HarbormasterBuildable::STATUS_PASSED;
} else {
$new_status = HarbormasterBuildable::STATUS_BUILDING;
// If we've been informed that the container for the buildable has
// changed, update it.
if ($update_container) {
$object = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->withPHIDs(array($buildable->getBuildablePHID()))
->executeOne();
if ($object) {
$buildable
->setContainerPHID($object->getHarbormasterContainerPHID())
->save();
}
}
$old_status = $buildable->getBuildableStatus();
$did_update = ($old_status != $new_status);
if ($did_update) {
$buildable->setBuildableStatus($new_status);
$buildable->save();
// Don't update the buildable status if we're still preparing builds: more
// builds may still be scheduled shortly, so even if every build we know
// about so far has passed, that doesn't mean the buildable has actually
// passed everything it needs to.
if (!$buildable->isPreparing()) {
$all_pass = true;
$any_fail = false;
foreach ($buildable->getBuilds() as $build) {
if (!$build->isPassed()) {
$all_pass = false;
}
if ($build->isComplete() && !$build->isPassed()) {
$any_fail = true;
}
}
if ($any_fail) {
$new_status = HarbormasterBuildableStatus::STATUS_FAILED;
} else if ($all_pass) {
$new_status = HarbormasterBuildableStatus::STATUS_PASSED;
} else {
$new_status = HarbormasterBuildableStatus::STATUS_BUILDING;
}
$old_status = $buildable->getBuildableStatus();
$did_update = ($old_status != $new_status);
if ($did_update) {
$buildable->setBuildableStatus($new_status);
$buildable->save();
}
}
$lock->unlock();
// Don't publish anything if we're still preparing builds.
if ($buildable->isPreparing()) {
return;
}
// If we changed the buildable status, try to post a transaction to the
// object about it. We can safely do this outside of the locked region.
@ -481,9 +538,10 @@ final class HarbormasterBuildEngine extends Phobject {
// can look at the results themselves, and other users generally don't
// care about the outcome.
$should_publish = $did_update &&
$new_status != HarbormasterBuildable::STATUS_BUILDING &&
!$buildable->getIsManualBuildable();
$should_publish =
($did_update) &&
($new_status != HarbormasterBuildableStatus::STATUS_BUILDING) &&
(!$buildable->getIsManualBuildable());
if (!$should_publish) {
return;

View file

@ -6,6 +6,9 @@ final class HarbormasterMessageType extends Phobject {
const MESSAGE_FAIL = 'fail';
const MESSAGE_WORK = 'work';
const BUILDABLE_BUILD = 'build';
const BUILDABLE_CONTAINER = 'container';
public static function getAllMessages() {
return array_keys(self::getMessageSpecifications());
}

View file

@ -87,13 +87,9 @@ final class HarbormasterUIEventListener
$status_view = new PHUIStatusListView();
$buildable_status = $buildable->getBuildableStatus();
$buildable_icon = HarbormasterBuildable::getBuildableStatusIcon(
$buildable_status);
$buildable_color = HarbormasterBuildable::getBuildableStatusColor(
$buildable_status);
$buildable_name = HarbormasterBuildable::getBuildableStatusName(
$buildable_status);
$buildable_icon = $buildable->getStatusIcon();
$buildable_color = $buildable->getStatusColor();
$buildable_name = $buildable->getStatusDisplayName();
$target = phutil_tag(
'a',

View file

@ -83,6 +83,11 @@ final class HarbormasterManagementBuildWorkflow
->setContainerPHID($buildable->getHarbormasterContainerPHID())
->save();
$buildable->sendMessage(
$viewer,
HarbormasterMessageType::BUILDABLE_BUILD,
false);
$console->writeOut(
"%s\n",
pht(

View file

@ -4,7 +4,7 @@ final class HarbormasterBuildMessageQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $buildTargetPHIDs;
private $receiverPHIDs;
private $consumed;
public function withIDs(array $ids) {
@ -12,8 +12,8 @@ final class HarbormasterBuildMessageQuery
return $this;
}
public function withBuildTargetPHIDs(array $phids) {
$this->buildTargetPHIDs = $phids;
public function withReceiverPHIDs(array $phids) {
$this->receiverPHIDs = $phids;
return $this;
}
@ -22,73 +22,67 @@ final class HarbormasterBuildMessageQuery
return $this;
}
public function newResultObject() {
return new HarbormasterBuildMessage();
}
protected function loadPage() {
$table = new HarbormasterBuildMessage();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
return $this->loadStandardPage($this->newResultObject());
}
protected function willFilterPage(array $page) {
$build_target_phids = array_filter(mpull($page, 'getBuildTargetPHID'));
if ($build_target_phids) {
$build_targets = id(new PhabricatorObjectQuery())
$receiver_phids = array_filter(mpull($page, 'getReceiverPHID'));
if ($receiver_phids) {
$receivers = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($build_target_phids)
->withPHIDs($receiver_phids)
->setParentQuery($this)
->execute();
$build_targets = mpull($build_targets, null, 'getPHID');
$receivers = mpull($receivers, null, 'getPHID');
} else {
$build_targets = array();
$receivers = array();
}
foreach ($page as $key => $message) {
$build_target_phid = $message->getBuildTargetPHID();
if (empty($build_targets[$build_target_phid])) {
$receiver_phid = $message->getReceiverPHID();
if (empty($receivers[$receiver_phid])) {
unset($page[$key]);
$this->didRejectResult($message);
continue;
}
$message->attachBuildTarget($build_targets[$build_target_phid]);
$message->attachReceiver($receivers[$receiver_phid]);
}
return $page;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids) {
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->buildTargetPHIDs) {
if ($this->receiverPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'buildTargetPHID IN (%Ls)',
$this->buildTargetPHIDs);
$conn,
'receiverPHID IN (%Ls)',
$this->receiverPHIDs);
}
if ($this->consumed !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'isConsumed = %d',
(int)$this->consumed);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
return $where;
}
public function getQueryApplicationClass() {

View file

@ -33,7 +33,7 @@ final class HarbormasterBuildableSearchEngine
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Statuses'))
->setOptions(HarbormasterBuildable::getBuildStatusMap())
->setOptions(HarbormasterBuildableStatus::getOptionMap())
->setDescription(pht('Search for builds by buildable status.')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Manual'))
@ -169,11 +169,9 @@ final class HarbormasterBuildableSearchEngine
$item->addIcon('fa-wrench grey', pht('Manual'));
}
$status = $buildable->getBuildableStatus();
$status_icon = HarbormasterBuildable::getBuildableStatusIcon($status);
$status_color = HarbormasterBuildable::getBuildableStatusColor($status);
$status_label = HarbormasterBuildable::getBuildableStatusName($status);
$status_icon = $buildable->getStatusIcon();
$status_color = $buildable->getStatusColor();
$status_label = $buildable->getStatusDisplayName();
$item->setStatusIcon("{$status_icon} {$status_color}", $status_label);

View file

@ -295,6 +295,18 @@ abstract class HarbormasterBuildStepImplementation extends Phobject {
->append($body);
}
protected function logSilencedCall(
HarbormasterBuild $build,
HarbormasterBuildTarget $build_target,
$label) {
$build_target
->newLog($label, 'silenced')
->append(
pht(
'Declining to make service call because `phabricator.silent` is '.
'enabled in configuration.'));
}
/* -( Automatic Targets )-------------------------------------------------- */

View file

@ -72,6 +72,11 @@ EOTEXT
HarbormasterBuildTarget $build_target) {
$viewer = PhabricatorUser::getOmnipotentUser();
if (PhabricatorEnv::getEnvConfig('phabricator.silent')) {
$this->logSilencedCall($build, $build_target, pht('Buildkite'));
throw new HarbormasterBuildFailureException();
}
$buildable = $build->getBuildable();
$object = $buildable->getBuildableObject();

View file

@ -84,6 +84,11 @@ EOTEXT
HarbormasterBuildTarget $build_target) {
$viewer = PhabricatorUser::getOmnipotentUser();
if (PhabricatorEnv::getEnvConfig('phabricator.silent')) {
$this->logSilencedCall($build, $build_target, pht('CircleCI'));
throw new HarbormasterBuildFailureException();
}
$buildable = $build->getBuildable();
$object = $buildable->getBuildableObject();

View file

@ -43,6 +43,12 @@ final class HarbormasterHTTPRequestBuildStepImplementation
HarbormasterBuildTarget $build_target) {
$viewer = PhabricatorUser::getOmnipotentUser();
if (PhabricatorEnv::getEnvConfig('phabricator.silent')) {
$this->logSilencedCall($build, $build_target, pht('HTTP Request'));
throw new HarbormasterBuildFailureException();
}
$settings = $this->getSettings();
$variables = $build_target->getVariables();

View file

@ -10,11 +10,11 @@ final class HarbormasterBuildMessage extends HarbormasterDAO
implements PhabricatorPolicyInterface {
protected $authorPHID;
protected $buildTargetPHID;
protected $receiverPHID;
protected $type;
protected $isConsumed;
private $buildTarget = self::ATTACHABLE;
private $receiver = self::ATTACHABLE;
public static function initializeNewMessage(PhabricatorUser $actor) {
$actor_phid = $actor->getPHID();
@ -34,19 +34,19 @@ final class HarbormasterBuildMessage extends HarbormasterDAO
'isConsumed' => 'bool',
),
self::CONFIG_KEY_SCHEMA => array(
'key_buildtarget' => array(
'columns' => array('buildTargetPHID'),
'key_receiver' => array(
'columns' => array('receiverPHID'),
),
),
) + parent::getConfiguration();
}
public function getBuildTarget() {
return $this->assertAttached($this->buildTarget);
public function getReceiver() {
return $this->assertAttached($this->receiver);
}
public function attachBuildTarget(HarbormasterBuildTarget $target) {
$this->buildTarget = $target;
public function attachReceiver($receiver) {
$this->receiver = $receiver;
return $this;
}
@ -61,17 +61,17 @@ final class HarbormasterBuildMessage extends HarbormasterDAO
}
public function getPolicy($capability) {
return $this->getBuildTarget()->getPolicy($capability);
return $this->getReceiver()->getPolicy($capability);
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return $this->getBuildTarget()->hasAutomaticCapability(
return $this->getReceiver()->hasAutomaticCapability(
$capability,
$viewer);
}
public function describeAutomaticCapability($capability) {
return pht('Build messages have the same policies as their targets.');
return pht('Build messages have the same policies as their receivers.');
}
}

View file

@ -15,53 +15,10 @@ final class HarbormasterBuildable extends HarbormasterDAO
private $containerObject = self::ATTACHABLE;
private $builds = self::ATTACHABLE;
const STATUS_BUILDING = 'building';
const STATUS_PASSED = 'passed';
const STATUS_FAILED = 'failed';
public static function getBuildableStatusName($status) {
$map = self::getBuildStatusMap();
return idx($map, $status, pht('Unknown ("%s")', $status));
}
public static function getBuildStatusMap() {
return array(
self::STATUS_BUILDING => pht('Building'),
self::STATUS_PASSED => pht('Passed'),
self::STATUS_FAILED => pht('Failed'),
);
}
public static function getBuildableStatusIcon($status) {
switch ($status) {
case self::STATUS_BUILDING:
return PHUIStatusItemView::ICON_RIGHT;
case self::STATUS_PASSED:
return PHUIStatusItemView::ICON_ACCEPT;
case self::STATUS_FAILED:
return PHUIStatusItemView::ICON_REJECT;
default:
return PHUIStatusItemView::ICON_QUESTION;
}
}
public static function getBuildableStatusColor($status) {
switch ($status) {
case self::STATUS_BUILDING:
return 'blue';
case self::STATUS_PASSED:
return 'green';
case self::STATUS_FAILED:
return 'red';
default:
return 'bluegrey';
}
}
public static function initializeNewBuildable(PhabricatorUser $actor) {
return id(new HarbormasterBuildable())
->setIsManualBuildable(0)
->setBuildableStatus(self::STATUS_BUILDING);
->setBuildableStatus(HarbormasterBuildableStatus::STATUS_PREPARING);
}
public function getMonogram() {
@ -250,6 +207,59 @@ final class HarbormasterBuildable extends HarbormasterDAO
}
/* -( Status )------------------------------------------------------------- */
public function getBuildableStatusObject() {
$status = $this->getBuildableStatus();
return HarbormasterBuildableStatus::newBuildableStatusObject($status);
}
public function getStatusIcon() {
return $this->getBuildableStatusObject()->getIcon();
}
public function getStatusDisplayName() {
return $this->getBuildableStatusObject()->getDisplayName();
}
public function getStatusColor() {
return $this->getBuildableStatusObject()->getColor();
}
public function isPreparing() {
return $this->getBuildableStatusObject()->isPreparing();
}
/* -( Messages )----------------------------------------------------------- */
public function sendMessage(
PhabricatorUser $viewer,
$message_type,
$queue_update) {
$message = HarbormasterBuildMessage::initializeNewMessage($viewer)
->setReceiverPHID($this->getPHID())
->setType($message_type)
->save();
if ($queue_update) {
PhabricatorWorker::scheduleTask(
'HarbormasterBuildWorker',
array(
'buildablePHID' => $this->getPHID(),
),
array(
'objectPHID' => $this->getPHID(),
));
}
return $message;
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */

View file

@ -108,9 +108,7 @@ final class HarbormasterBuild extends HarbormasterDAO
}
public function isBuilding() {
return
$this->getBuildStatus() === HarbormasterBuildStatus::STATUS_PENDING ||
$this->getBuildStatus() === HarbormasterBuildStatus::STATUS_BUILDING;
return $this->getBuildStatusObject()->isBuilding();
}
public function isAutobuild() {
@ -173,13 +171,15 @@ final class HarbormasterBuild extends HarbormasterDAO
}
public function isComplete() {
return in_array(
$this->getBuildStatus(),
HarbormasterBuildStatus::getCompletedStatusConstants());
return $this->getBuildStatusObject()->isComplete();
}
public function isPaused() {
return ($this->getBuildStatus() == HarbormasterBuildStatus::STATUS_PAUSED);
return $this->getBuildStatusObject()->isPaused();
}
public function isPassed() {
return $this->getBuildStatusObject()->isPassed();
}
public function getURI() {
@ -187,6 +187,11 @@ final class HarbormasterBuild extends HarbormasterDAO
return "/harbormaster/build/{$id}/";
}
protected function getBuildStatusObject() {
$status_key = $this->getBuildStatus();
return HarbormasterBuildStatus::newBuildStatusObject($status_key);
}
/* -( Build Commands )----------------------------------------------------- */

View file

@ -17,12 +17,21 @@ final class HarbormasterBuildWorker extends HarbormasterWorker {
protected function doWork() {
$viewer = $this->getViewer();
$build = $this->loadBuild();
id(new HarbormasterBuildEngine())
->setViewer($viewer)
->setBuild($build)
->continueBuild();
$engine = id(new HarbormasterBuildEngine())
->setViewer($viewer);
$data = $this->getTaskData();
$build_id = idx($data, 'buildID');
if ($build_id) {
$build = $this->loadBuild();
$engine->setBuild($build);
$engine->continueBuild();
} else {
$buildable = $this->loadBuildable();
$engine->updateBuildable($buildable);
}
}
private function loadBuild() {
@ -42,4 +51,21 @@ final class HarbormasterBuildWorker extends HarbormasterWorker {
return $build;
}
private function loadBuildable() {
$data = $this->getTaskData();
$phid = idx($data, 'buildablePHID');
$viewer = $this->getViewer();
$buildable = id(new HarbormasterBuildableQuery())
->setViewer($viewer)
->withPHIDs(array($phid))
->executeOne();
if (!$buildable) {
throw new PhabricatorWorkerPermanentFailureException(
pht('Invalid buildable PHID "%s".', $phid));
}
return $buildable;
}
}

View file

@ -14,6 +14,10 @@ final class HeraldCallWebhookAction extends HeraldAction {
}
public function supportsObject($object) {
if (!$this->getAdapter()->supportsWebhooks()) {
return false;
}
return true;
}

View file

@ -1211,6 +1211,11 @@ abstract class HeraldAdapter extends Phobject {
/* -( Webhooks )----------------------------------------------------------- */
public function supportsWebhooks() {
return true;
}
final public function queueWebhook($webhook_phid, $rule_phid) {
$this->webhookMap[$webhook_phid][] = $rule_phid;
return $this;

View file

@ -32,6 +32,13 @@ final class HeraldWebhookWorker
$status));
}
// If we're in silent mode, permanently fail the webhook request and then
// return to complete this task.
if (PhabricatorEnv::getEnvConfig('phabricator.silent')) {
$this->failRequest($request, 'hook', 'silent');
return;
}
$hook = $request->getWebhook();
if ($hook->isDisabled()) {

View file

@ -1,7 +1,7 @@
<?php
final class PhabricatorQuickSearchApplicationEngineExtension
extends PhabricatorQuickSearchEngineExtension {
final class PhabricatorDatasourceApplicationEngineExtension
extends PhabricatorDatasourceEngineExtension {
public function newQuickSearchDatasources() {
return array(

View file

@ -64,4 +64,8 @@ final class PhabricatorMailOutboundMailHeraldAdapter
return pht('Mail %d', $this->getObject()->getID());
}
public function supportsWebhooks() {
return false;
}
}

View file

@ -13,6 +13,7 @@ final class PhabricatorMetaMTAMailBody extends Phobject {
private $attachments = array();
private $viewer;
private $contextObject;
public function getViewer() {
return $this->viewer;
@ -23,6 +24,16 @@ final class PhabricatorMetaMTAMailBody extends Phobject {
return $this;
}
public function setContextObject($context_object) {
$this->contextObject = $context_object;
return $this;
}
public function getContextObject() {
return $this->contextObject;
}
/* -( Composition )-------------------------------------------------------- */
@ -45,9 +56,9 @@ final class PhabricatorMetaMTAMailBody extends Phobject {
public function addRemarkupSection($header, $text) {
try {
$engine = PhabricatorMarkupEngine::newMarkupEngine(array());
$engine->setConfig('viewer', $this->getViewer());
$engine->setMode(PhutilRemarkupEngine::MODE_TEXT);
$engine = $this->newMarkupEngine()
->setMode(PhutilRemarkupEngine::MODE_TEXT);
$styled_text = $engine->markupText($text);
$this->addPlaintextSection($header, $styled_text);
} catch (Exception $ex) {
@ -56,12 +67,9 @@ final class PhabricatorMetaMTAMailBody extends Phobject {
}
try {
$mail_engine = PhabricatorMarkupEngine::newMarkupEngine(array());
$mail_engine->setConfig('viewer', $this->getViewer());
$mail_engine->setMode(PhutilRemarkupEngine::MODE_HTML_MAIL);
$mail_engine->setConfig(
'uri.base',
PhabricatorEnv::getProductionURI('/'));
$mail_engine = $this->newMarkupEngine()
->setMode(PhutilRemarkupEngine::MODE_HTML_MAIL);
$html = $mail_engine->markupText($text);
$this->addHTMLSection($header, $html);
} catch (Exception $ex) {
@ -215,4 +223,19 @@ final class PhabricatorMetaMTAMailBody extends Phobject {
private function indent($text) {
return rtrim(" ".str_replace("\n", "\n ", $text));
}
private function newMarkupEngine() {
$engine = PhabricatorMarkupEngine::newMarkupEngine(array())
->setConfig('viewer', $this->getViewer())
->setConfig('uri.base', PhabricatorEnv::getProductionURI('/'));
$context = $this->getContextObject();
if ($context) {
$engine->setConfig('contextObject', $context);
}
return $engine;
}
}

View file

@ -0,0 +1,36 @@
<?php
final class PhabricatorPeopleDatasourceEngineExtension
extends PhabricatorDatasourceEngineExtension {
public function newQuickSearchDatasources() {
return array(
new PhabricatorPeopleDatasource(),
);
}
public function newJumpURI($query) {
$viewer = $this->getViewer();
// Send "u" to the user directory.
if (preg_match('/^u\z/i', $query)) {
return '/people/';
}
// Send "u <string>" to the user's profile page.
$matches = null;
if (preg_match('/^u\s+(.+)\z/i', $query, $matches)) {
$raw_query = $matches[1];
// TODO: We could test that this is a valid username and jump to
// a search in the user directory if it isn't.
return urisprintf(
'/p/%s/',
$raw_query);
}
return null;
}
}

View file

@ -1,11 +0,0 @@
<?php
final class PhabricatorPeopleQuickSearchEngineExtension
extends PhabricatorQuickSearchEngineExtension {
public function newQuickSearchDatasources() {
return array(
new PhabricatorPeopleDatasource(),
);
}
}

View file

@ -0,0 +1,18 @@
<?php
final class PhrictionContentSearchConduitAPIMethod
extends PhabricatorSearchEngineAPIMethod {
public function getAPIMethodName() {
return 'phriction.content.search';
}
public function newSearchEngine() {
return new PhrictionContentSearchEngine();
}
public function getMethodSummary() {
return pht('Read information about Phriction document history.');
}
}

View file

@ -57,7 +57,7 @@ final class PhrictionCreateConduitAPIMethod extends PhrictionConduitAPIMethod {
->setActor($request->getUser())
->setContentSource($request->newContentSource())
->setContinueOnNoEffect(true)
->setDescription($request->getValue('description'));
->setDescription((string)$request->getValue('description'));
try {
$editor->applyTransactions($doc, $xactions);

View file

@ -0,0 +1,18 @@
<?php
final class PhrictionDocumentSearchConduitAPIMethod
extends PhabricatorSearchEngineAPIMethod {
public function getAPIMethodName() {
return 'phriction.document.search';
}
public function newSearchEngine() {
return new PhrictionDocumentSearchEngine();
}
public function getMethodSummary() {
return pht('Read information about Phriction documents.');
}
}

View file

@ -52,7 +52,7 @@ final class PhrictionEditConduitAPIMethod extends PhrictionConduitAPIMethod {
->setActor($request->getUser())
->setContentSource($request->newContentSource())
->setContinueOnNoEffect(true)
->setDescription($request->getValue('description'));
->setDescription((string)$request->getValue('description'));
try {
$editor->applyTransactions($doc, $xactions);

Some files were not shown because too many files have changed in this diff Show more