mirror of
https://we.phorge.it/source/phorge.git
synced 2025-03-14 13:24:57 +01:00
(stable) Promote 2018 Week 14
This commit is contained in:
commit
fba35975e7
44 changed files with 1307 additions and 465 deletions
|
@ -9,7 +9,7 @@ return array(
|
|||
'names' => array(
|
||||
'conpherence.pkg.css' => 'e68cf1fa',
|
||||
'conpherence.pkg.js' => '15191c65',
|
||||
'core.pkg.css' => '1dd5fa4b',
|
||||
'core.pkg.css' => '49b87886',
|
||||
'core.pkg.js' => '1ea38af8',
|
||||
'differential.pkg.css' => '113e692c',
|
||||
'differential.pkg.js' => 'f6d809c0',
|
||||
|
@ -132,7 +132,7 @@ return array(
|
|||
'rsrc/css/phui/object-item/phui-oi-color.css' => 'cd2b9b77',
|
||||
'rsrc/css/phui/object-item/phui-oi-drag-ui.css' => '08f4ccc3',
|
||||
'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '9d9685d6',
|
||||
'rsrc/css/phui/object-item/phui-oi-list-view.css' => '6ae18df0',
|
||||
'rsrc/css/phui/object-item/phui-oi-list-view.css' => 'ae1404ba',
|
||||
'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => 'a8beebea',
|
||||
'rsrc/css/phui/phui-action-list.css' => '0bcd9a45',
|
||||
'rsrc/css/phui/phui-action-panel.css' => 'b4798122',
|
||||
|
@ -158,7 +158,7 @@ return array(
|
|||
'rsrc/css/phui/phui-header-view.css' => '31dc6c72',
|
||||
'rsrc/css/phui/phui-hovercard.css' => 'f0592bcf',
|
||||
'rsrc/css/phui/phui-icon-set-selector.css' => '87db8fee',
|
||||
'rsrc/css/phui/phui-icon.css' => '5c4a5de6',
|
||||
'rsrc/css/phui/phui-icon.css' => 'cf24ceec',
|
||||
'rsrc/css/phui/phui-image-mask.css' => 'a8498f9c',
|
||||
'rsrc/css/phui/phui-info-view.css' => 'e929f98c',
|
||||
'rsrc/css/phui/phui-invisible-character-view.css' => '6993d9f0',
|
||||
|
@ -833,7 +833,7 @@ return array(
|
|||
'phui-hovercard' => '1bd28176',
|
||||
'phui-hovercard-view-css' => 'f0592bcf',
|
||||
'phui-icon-set-selector-css' => '87db8fee',
|
||||
'phui-icon-view-css' => '5c4a5de6',
|
||||
'phui-icon-view-css' => 'cf24ceec',
|
||||
'phui-image-mask-css' => 'a8498f9c',
|
||||
'phui-info-view-css' => 'e929f98c',
|
||||
'phui-inline-comment-view-css' => '65ae3bc2',
|
||||
|
@ -846,7 +846,7 @@ return array(
|
|||
'phui-oi-color-css' => 'cd2b9b77',
|
||||
'phui-oi-drag-ui-css' => '08f4ccc3',
|
||||
'phui-oi-flush-ui-css' => '9d9685d6',
|
||||
'phui-oi-list-view-css' => '6ae18df0',
|
||||
'phui-oi-list-view-css' => 'ae1404ba',
|
||||
'phui-oi-simple-ui-css' => 'a8beebea',
|
||||
'phui-pager-css' => 'edcbc226',
|
||||
'phui-pinboard-view-css' => '2495140e',
|
||||
|
|
20
resources/sql/autopatches/20180403.draft.01.broadcast.php
Normal file
20
resources/sql/autopatches/20180403.draft.01.broadcast.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
$table = new DifferentialRevision();
|
||||
$conn = $table->establishConnection('w');
|
||||
|
||||
$drafts = $table->loadAllWhere(
|
||||
'status = %s',
|
||||
DifferentialRevisionStatus::DRAFT);
|
||||
foreach ($drafts as $draft) {
|
||||
$properties = $draft->getProperties();
|
||||
|
||||
$properties[DifferentialRevision::PROPERTY_SHOULD_BROADCAST] = false;
|
||||
|
||||
queryfx(
|
||||
$conn,
|
||||
'UPDATE %T SET properties = %s WHERE id = %d',
|
||||
id(new DifferentialRevision())->getTableName(),
|
||||
phutil_json_encode($properties),
|
||||
$draft->getID());
|
||||
}
|
|
@ -380,6 +380,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialBlockHeraldAction' => 'applications/differential/herald/DifferentialBlockHeraldAction.php',
|
||||
'DifferentialBlockingReviewerDatasource' => 'applications/differential/typeahead/DifferentialBlockingReviewerDatasource.php',
|
||||
'DifferentialBranchField' => 'applications/differential/customfield/DifferentialBranchField.php',
|
||||
'DifferentialBuildableEngine' => 'applications/differential/harbormaster/DifferentialBuildableEngine.php',
|
||||
'DifferentialChangeDetailMailView' => 'applications/differential/mail/DifferentialChangeDetailMailView.php',
|
||||
'DifferentialChangeHeraldFieldGroup' => 'applications/differential/herald/DifferentialChangeHeraldFieldGroup.php',
|
||||
'DifferentialChangeType' => 'applications/differential/constants/DifferentialChangeType.php',
|
||||
|
@ -388,6 +389,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialChangesetDetailView' => 'applications/differential/view/DifferentialChangesetDetailView.php',
|
||||
'DifferentialChangesetFileTreeSideNavBuilder' => 'applications/differential/view/DifferentialChangesetFileTreeSideNavBuilder.php',
|
||||
'DifferentialChangesetHTMLRenderer' => 'applications/differential/render/DifferentialChangesetHTMLRenderer.php',
|
||||
'DifferentialChangesetListController' => 'applications/differential/controller/DifferentialChangesetListController.php',
|
||||
'DifferentialChangesetListView' => 'applications/differential/view/DifferentialChangesetListView.php',
|
||||
'DifferentialChangesetOneUpMailRenderer' => 'applications/differential/render/DifferentialChangesetOneUpMailRenderer.php',
|
||||
'DifferentialChangesetOneUpRenderer' => 'applications/differential/render/DifferentialChangesetOneUpRenderer.php',
|
||||
|
@ -396,6 +398,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialChangesetParserTestCase' => 'applications/differential/parser/__tests__/DifferentialChangesetParserTestCase.php',
|
||||
'DifferentialChangesetQuery' => 'applications/differential/query/DifferentialChangesetQuery.php',
|
||||
'DifferentialChangesetRenderer' => 'applications/differential/render/DifferentialChangesetRenderer.php',
|
||||
'DifferentialChangesetSearchEngine' => 'applications/differential/query/DifferentialChangesetSearchEngine.php',
|
||||
'DifferentialChangesetTestRenderer' => 'applications/differential/render/DifferentialChangesetTestRenderer.php',
|
||||
'DifferentialChangesetTwoUpRenderer' => 'applications/differential/render/DifferentialChangesetTwoUpRenderer.php',
|
||||
'DifferentialChangesetTwoUpTestRenderer' => 'applications/differential/render/DifferentialChangesetTwoUpTestRenderer.php',
|
||||
|
@ -529,6 +532,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialRevisionAffectedFilesHeraldField' => 'applications/differential/herald/DifferentialRevisionAffectedFilesHeraldField.php',
|
||||
'DifferentialRevisionAuthorHeraldField' => 'applications/differential/herald/DifferentialRevisionAuthorHeraldField.php',
|
||||
'DifferentialRevisionAuthorProjectsHeraldField' => 'applications/differential/herald/DifferentialRevisionAuthorProjectsHeraldField.php',
|
||||
'DifferentialRevisionBuildableTransaction' => 'applications/differential/xaction/DifferentialRevisionBuildableTransaction.php',
|
||||
'DifferentialRevisionCloseDetailsController' => 'applications/differential/controller/DifferentialRevisionCloseDetailsController.php',
|
||||
'DifferentialRevisionCloseTransaction' => 'applications/differential/xaction/DifferentialRevisionCloseTransaction.php',
|
||||
'DifferentialRevisionClosedStatusDatasource' => 'applications/differential/typeahead/DifferentialRevisionClosedStatusDatasource.php',
|
||||
|
@ -638,6 +642,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionBrowseQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionBrowseQueryConduitAPIMethod.php',
|
||||
'DiffusionBrowseResultSet' => 'applications/diffusion/data/DiffusionBrowseResultSet.php',
|
||||
'DiffusionBrowseTableView' => 'applications/diffusion/view/DiffusionBrowseTableView.php',
|
||||
'DiffusionBuildableEngine' => 'applications/diffusion/harbormaster/DiffusionBuildableEngine.php',
|
||||
'DiffusionCacheEngineExtension' => 'applications/diffusion/engineextension/DiffusionCacheEngineExtension.php',
|
||||
'DiffusionCachedResolveRefsQuery' => 'applications/diffusion/query/DiffusionCachedResolveRefsQuery.php',
|
||||
'DiffusionChangeController' => 'applications/diffusion/controller/DiffusionChangeController.php',
|
||||
|
@ -657,6 +662,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionCommitAutocloseHeraldField' => 'applications/diffusion/herald/DiffusionCommitAutocloseHeraldField.php',
|
||||
'DiffusionCommitBranchesController' => 'applications/diffusion/controller/DiffusionCommitBranchesController.php',
|
||||
'DiffusionCommitBranchesHeraldField' => 'applications/diffusion/herald/DiffusionCommitBranchesHeraldField.php',
|
||||
'DiffusionCommitBuildableTransaction' => 'applications/diffusion/xaction/DiffusionCommitBuildableTransaction.php',
|
||||
'DiffusionCommitCommitterHeraldField' => 'applications/diffusion/herald/DiffusionCommitCommitterHeraldField.php',
|
||||
'DiffusionCommitCommitterProjectsHeraldField' => 'applications/diffusion/herald/DiffusionCommitCommitterProjectsHeraldField.php',
|
||||
'DiffusionCommitConcernTransaction' => 'applications/diffusion/xaction/DiffusionCommitConcernTransaction.php',
|
||||
|
@ -1285,6 +1291,7 @@ phutil_register_library_map(array(
|
|||
'HarbormasterBuildable' => 'applications/harbormaster/storage/HarbormasterBuildable.php',
|
||||
'HarbormasterBuildableActionController' => 'applications/harbormaster/controller/HarbormasterBuildableActionController.php',
|
||||
'HarbormasterBuildableAdapterInterface' => 'applications/harbormaster/herald/HarbormasterBuildableAdapterInterface.php',
|
||||
'HarbormasterBuildableEngine' => 'applications/harbormaster/engine/HarbormasterBuildableEngine.php',
|
||||
'HarbormasterBuildableInterface' => 'applications/harbormaster/interface/HarbormasterBuildableInterface.php',
|
||||
'HarbormasterBuildableListController' => 'applications/harbormaster/controller/HarbormasterBuildableListController.php',
|
||||
'HarbormasterBuildablePHIDType' => 'applications/harbormaster/phid/HarbormasterBuildablePHIDType.php',
|
||||
|
@ -1321,6 +1328,7 @@ phutil_register_library_map(array(
|
|||
'HarbormasterLogWorker' => 'applications/harbormaster/worker/HarbormasterLogWorker.php',
|
||||
'HarbormasterManagementArchiveLogsWorkflow' => 'applications/harbormaster/management/HarbormasterManagementArchiveLogsWorkflow.php',
|
||||
'HarbormasterManagementBuildWorkflow' => 'applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php',
|
||||
'HarbormasterManagementPublishWorkflow' => 'applications/harbormaster/management/HarbormasterManagementPublishWorkflow.php',
|
||||
'HarbormasterManagementRebuildLogWorkflow' => 'applications/harbormaster/management/HarbormasterManagementRebuildLogWorkflow.php',
|
||||
'HarbormasterManagementRestartWorkflow' => 'applications/harbormaster/management/HarbormasterManagementRestartWorkflow.php',
|
||||
'HarbormasterManagementUpdateWorkflow' => 'applications/harbormaster/management/HarbormasterManagementUpdateWorkflow.php',
|
||||
|
@ -5586,6 +5594,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialBlockHeraldAction' => 'HeraldAction',
|
||||
'DifferentialBlockingReviewerDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||
'DifferentialBranchField' => 'DifferentialCustomField',
|
||||
'DifferentialBuildableEngine' => 'HarbormasterBuildableEngine',
|
||||
'DifferentialChangeDetailMailView' => 'DifferentialMailView',
|
||||
'DifferentialChangeHeraldFieldGroup' => 'HeraldFieldGroup',
|
||||
'DifferentialChangeType' => 'Phobject',
|
||||
|
@ -5598,6 +5607,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialChangesetDetailView' => 'AphrontView',
|
||||
'DifferentialChangesetFileTreeSideNavBuilder' => 'Phobject',
|
||||
'DifferentialChangesetHTMLRenderer' => 'DifferentialChangesetRenderer',
|
||||
'DifferentialChangesetListController' => 'DifferentialController',
|
||||
'DifferentialChangesetListView' => 'AphrontView',
|
||||
'DifferentialChangesetOneUpMailRenderer' => 'DifferentialChangesetRenderer',
|
||||
'DifferentialChangesetOneUpRenderer' => 'DifferentialChangesetHTMLRenderer',
|
||||
|
@ -5606,6 +5616,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialChangesetParserTestCase' => 'PhabricatorTestCase',
|
||||
'DifferentialChangesetQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'DifferentialChangesetRenderer' => 'Phobject',
|
||||
'DifferentialChangesetSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'DifferentialChangesetTestRenderer' => 'DifferentialChangesetRenderer',
|
||||
'DifferentialChangesetTwoUpRenderer' => 'DifferentialChangesetHTMLRenderer',
|
||||
'DifferentialChangesetTwoUpTestRenderer' => 'DifferentialChangesetTestRenderer',
|
||||
|
@ -5774,6 +5785,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialRevisionAffectedFilesHeraldField' => 'DifferentialRevisionHeraldField',
|
||||
'DifferentialRevisionAuthorHeraldField' => 'DifferentialRevisionHeraldField',
|
||||
'DifferentialRevisionAuthorProjectsHeraldField' => 'DifferentialRevisionHeraldField',
|
||||
'DifferentialRevisionBuildableTransaction' => 'DifferentialRevisionTransactionType',
|
||||
'DifferentialRevisionCloseDetailsController' => 'DifferentialController',
|
||||
'DifferentialRevisionCloseTransaction' => 'DifferentialRevisionActionTransaction',
|
||||
'DifferentialRevisionClosedStatusDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
|
@ -5883,6 +5895,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionBrowseQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
|
||||
'DiffusionBrowseResultSet' => 'Phobject',
|
||||
'DiffusionBrowseTableView' => 'DiffusionView',
|
||||
'DiffusionBuildableEngine' => 'HarbormasterBuildableEngine',
|
||||
'DiffusionCacheEngineExtension' => 'PhabricatorCacheEngineExtension',
|
||||
'DiffusionCachedResolveRefsQuery' => 'DiffusionLowLevelQuery',
|
||||
'DiffusionChangeController' => 'DiffusionController',
|
||||
|
@ -5902,6 +5915,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionCommitAutocloseHeraldField' => 'DiffusionCommitHeraldField',
|
||||
'DiffusionCommitBranchesController' => 'DiffusionController',
|
||||
'DiffusionCommitBranchesHeraldField' => 'DiffusionCommitHeraldField',
|
||||
'DiffusionCommitBuildableTransaction' => 'DiffusionCommitTransactionType',
|
||||
'DiffusionCommitCommitterHeraldField' => 'DiffusionCommitHeraldField',
|
||||
'DiffusionCommitCommitterProjectsHeraldField' => 'DiffusionCommitHeraldField',
|
||||
'DiffusionCommitConcernTransaction' => 'DiffusionCommitAuditTransaction',
|
||||
|
@ -6636,6 +6650,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorDestructibleInterface',
|
||||
),
|
||||
'HarbormasterBuildableActionController' => 'HarbormasterController',
|
||||
'HarbormasterBuildableEngine' => 'Phobject',
|
||||
'HarbormasterBuildableListController' => 'HarbormasterController',
|
||||
'HarbormasterBuildablePHIDType' => 'PhabricatorPHIDType',
|
||||
'HarbormasterBuildableQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
|
@ -6669,6 +6684,7 @@ phutil_register_library_map(array(
|
|||
'HarbormasterLogWorker' => 'HarbormasterWorker',
|
||||
'HarbormasterManagementArchiveLogsWorkflow' => 'HarbormasterManagementWorkflow',
|
||||
'HarbormasterManagementBuildWorkflow' => 'HarbormasterManagementWorkflow',
|
||||
'HarbormasterManagementPublishWorkflow' => 'HarbormasterManagementWorkflow',
|
||||
'HarbormasterManagementRebuildLogWorkflow' => 'HarbormasterManagementWorkflow',
|
||||
'HarbormasterManagementRestartWorkflow' => 'HarbormasterManagementWorkflow',
|
||||
'HarbormasterManagementUpdateWorkflow' => 'HarbormasterManagementWorkflow',
|
||||
|
|
|
@ -52,7 +52,13 @@ final class PhabricatorDifferentialApplication extends PhabricatorApplication {
|
|||
'(?:query/(?P<queryKey>[^/]+)/)?'
|
||||
=> 'DifferentialRevisionListController',
|
||||
'diff/' => array(
|
||||
'(?P<id>[1-9]\d*)/' => 'DifferentialDiffViewController',
|
||||
'(?P<id>[1-9]\d*)/' => array(
|
||||
'' => 'DifferentialDiffViewController',
|
||||
'changesets/' => array(
|
||||
$this->getQueryRoutePattern()
|
||||
=> 'DifferentialChangesetListController',
|
||||
),
|
||||
),
|
||||
'create/' => 'DifferentialDiffCreateController',
|
||||
),
|
||||
'changeset/' => 'DifferentialChangesetViewController',
|
||||
|
|
|
@ -56,10 +56,7 @@ final class DifferentialCreateRawDiffConduitAPIMethod
|
|||
throw new Exception(
|
||||
pht(
|
||||
'The raw diff you have submitted is too large to parse (it affects '.
|
||||
'more than %s paths and hunks). Differential should only be used '.
|
||||
'for changes which are small enough to receive detailed human '.
|
||||
'review. See "Differential User Guide: Large Changes" in the '.
|
||||
'documentation for more information.',
|
||||
'more than %s paths and hunks).',
|
||||
new PhutilNumber($raw_limit)));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialChangesetListController
|
||||
extends DifferentialController {
|
||||
|
||||
private $diff;
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$diff = id(new DifferentialDiffQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($request->getURIData('id')))
|
||||
->executeOne();
|
||||
if (!$diff) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$this->diff = $diff;
|
||||
|
||||
return id(new DifferentialChangesetSearchEngine())
|
||||
->setController($this)
|
||||
->setDiff($diff)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
protected function buildApplicationCrumbs() {
|
||||
$crumbs = parent::buildApplicationCrumbs();
|
||||
|
||||
$diff = $this->diff;
|
||||
if ($diff) {
|
||||
$revision = $diff->getRevision();
|
||||
if ($revision) {
|
||||
$crumbs->addTextCrumb(
|
||||
$revision->getMonogram(),
|
||||
$revision->getURI());
|
||||
}
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Diff %d', $diff->getID()),
|
||||
$diff->getURI());
|
||||
}
|
||||
|
||||
return $crumbs;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -3,11 +3,20 @@
|
|||
final class DifferentialRevisionViewController extends DifferentialController {
|
||||
|
||||
private $revisionID;
|
||||
private $veryLargeDiff;
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isVeryLargeDiff() {
|
||||
return $this->veryLargeDiff;
|
||||
}
|
||||
|
||||
public function getVeryLargeDiffLimit() {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
$this->revisionID = $request->getURIData('id');
|
||||
|
@ -73,6 +82,10 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
|||
idx($diffs, $diff_vs),
|
||||
$repository);
|
||||
|
||||
if (count($rendering_references) > $this->getVeryLargeDiffLimit()) {
|
||||
$this->veryLargeDiff = true;
|
||||
}
|
||||
|
||||
if ($request->getExists('download')) {
|
||||
return $this->buildRawDiffResponse(
|
||||
$revision,
|
||||
|
@ -145,12 +158,12 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
|||
if (count($changesets) > $limit && !$large) {
|
||||
$count = count($changesets);
|
||||
$warning = new PHUIInfoView();
|
||||
$warning->setTitle(pht('Very Large Diff'));
|
||||
$warning->setTitle(pht('Large Diff'));
|
||||
$warning->setSeverity(PHUIInfoView::SEVERITY_WARNING);
|
||||
$warning->appendChild(hsprintf(
|
||||
'%s <strong>%s</strong>',
|
||||
pht(
|
||||
'This diff is very large and affects %s files. '.
|
||||
'This diff is large and affects %s files. '.
|
||||
'You may load each file individually or ',
|
||||
new PhutilNumber($count)),
|
||||
phutil_tag(
|
||||
|
@ -265,35 +278,53 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
|||
|
||||
$timeline->setQuoteRef($revision->getMonogram());
|
||||
|
||||
$changeset_view = id(new DifferentialChangesetListView())
|
||||
->setChangesets($changesets)
|
||||
->setVisibleChangesets($visible_changesets)
|
||||
->setStandaloneURI('/differential/changeset/')
|
||||
->setRawFileURIs(
|
||||
'/differential/changeset/?view=old',
|
||||
'/differential/changeset/?view=new')
|
||||
->setUser($viewer)
|
||||
->setDiff($target)
|
||||
->setRenderingReferences($rendering_references)
|
||||
->setVsMap($vs_map)
|
||||
->setWhitespace($whitespace)
|
||||
->setSymbolIndexes($symbol_indexes)
|
||||
->setTitle(pht('Diff %s', $target->getID()))
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY);
|
||||
if ($this->isVeryLargeDiff()) {
|
||||
$messages = array();
|
||||
|
||||
$messages[] = pht(
|
||||
'This very large diff affects more than %s files. Use the %s to '.
|
||||
'browse changes.',
|
||||
new PhutilNumber($this->getVeryLargeDiffLimit()),
|
||||
phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/differential/diff/'.$target->getID().'/changesets/',
|
||||
),
|
||||
phutil_tag('strong', array(), pht('Changeset List'))));
|
||||
|
||||
$changeset_view = id(new PHUIInfoView())
|
||||
->setErrors($messages);
|
||||
} else {
|
||||
$changeset_view = id(new DifferentialChangesetListView())
|
||||
->setChangesets($changesets)
|
||||
->setVisibleChangesets($visible_changesets)
|
||||
->setStandaloneURI('/differential/changeset/')
|
||||
->setRawFileURIs(
|
||||
'/differential/changeset/?view=old',
|
||||
'/differential/changeset/?view=new')
|
||||
->setUser($viewer)
|
||||
->setDiff($target)
|
||||
->setRenderingReferences($rendering_references)
|
||||
->setVsMap($vs_map)
|
||||
->setWhitespace($whitespace)
|
||||
->setSymbolIndexes($symbol_indexes)
|
||||
->setTitle(pht('Diff %s', $target->getID()))
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY);
|
||||
|
||||
|
||||
$revision_id = $revision->getID();
|
||||
$inline_list_uri = "/revision/inlines/{$revision_id}/";
|
||||
$inline_list_uri = $this->getApplicationURI($inline_list_uri);
|
||||
$changeset_view->setInlineListURI($inline_list_uri);
|
||||
$revision_id = $revision->getID();
|
||||
$inline_list_uri = "/revision/inlines/{$revision_id}/";
|
||||
$inline_list_uri = $this->getApplicationURI($inline_list_uri);
|
||||
$changeset_view->setInlineListURI($inline_list_uri);
|
||||
|
||||
if ($repository) {
|
||||
$changeset_view->setRepository($repository);
|
||||
}
|
||||
if ($repository) {
|
||||
$changeset_view->setRepository($repository);
|
||||
}
|
||||
|
||||
if (!$viewer_is_anonymous) {
|
||||
$changeset_view->setInlineCommentControllerURI(
|
||||
'/differential/comment/inline/edit/'.$revision->getID().'/');
|
||||
if (!$viewer_is_anonymous) {
|
||||
$changeset_view->setInlineCommentControllerURI(
|
||||
'/differential/comment/inline/edit/'.$revision->getID().'/');
|
||||
}
|
||||
}
|
||||
|
||||
$broken_diffs = $this->loadHistoryDiffStatus($diffs);
|
||||
|
@ -312,7 +343,7 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
|||
->setLocalCommits(idx($props, 'local:commits'))
|
||||
->setCommitsForLinks($commits_for_links);
|
||||
|
||||
if ($repository) {
|
||||
if ($repository && !$this->isVeryLargeDiff()) {
|
||||
$other_revisions = $this->loadOtherRevisions(
|
||||
$changesets,
|
||||
$target,
|
||||
|
@ -328,10 +359,14 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
|||
|
||||
$this->buildPackageMaps($changesets);
|
||||
|
||||
$toc_view = $this->buildTableOfContents(
|
||||
$changesets,
|
||||
$visible_changesets,
|
||||
$target->loadCoverageMap($viewer));
|
||||
if ($this->isVeryLargeDiff()) {
|
||||
$toc_view = null;
|
||||
} else {
|
||||
$toc_view = $this->buildTableOfContents(
|
||||
$changesets,
|
||||
$visible_changesets,
|
||||
$target->loadCoverageMap($viewer));
|
||||
}
|
||||
|
||||
// Attach changesets to each reviewer so we can show which Owners package
|
||||
// reviewers own no files.
|
||||
|
@ -341,12 +376,17 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
|||
$reviewer->attachChangesets($reviewer_changesets);
|
||||
}
|
||||
|
||||
$tab_group = id(new PHUITabGroupView())
|
||||
->addTab(
|
||||
$tab_group = id(new PHUITabGroupView());
|
||||
|
||||
if ($toc_view) {
|
||||
$tab_group->addTab(
|
||||
id(new PHUITabView())
|
||||
->setName(pht('Files'))
|
||||
->setKey('files')
|
||||
->appendChild($toc_view))
|
||||
->appendChild($toc_view));
|
||||
}
|
||||
|
||||
$tab_group
|
||||
->addTab(
|
||||
id(new PHUITabView())
|
||||
->setName(pht('History'))
|
||||
|
@ -399,8 +439,18 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
|||
->appendChild($other_view));
|
||||
}
|
||||
|
||||
$view_button = id(new PHUIButtonView())
|
||||
->setTag('a')
|
||||
->setText(pht('Changeset List'))
|
||||
->setHref('/differential/diff/'.$target->getID().'/changesets/')
|
||||
->setIcon('fa-align-left');
|
||||
|
||||
$tab_header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Revision Contents'))
|
||||
->addActionLink($view_button);
|
||||
|
||||
$tab_view = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Revision Contents'))
|
||||
->setHeader($tab_header)
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->addTabGroup($tab_group);
|
||||
|
||||
|
@ -469,7 +519,7 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
|||
PhabricatorShowFiletreeSetting::VALUE_ENABLE_FILETREE);
|
||||
|
||||
$nav = null;
|
||||
if ($filetree_on) {
|
||||
if ($filetree_on && !$this->isVeryLargeDiff()) {
|
||||
$collapsed_key = PhabricatorFiletreeVisibleSetting::SETTINGKEY;
|
||||
$collapsed_value = $viewer->getUserSetting($collapsed_key);
|
||||
|
||||
|
@ -525,11 +575,27 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
|||
$status_tag = id(new PHUITagView())
|
||||
->setName($revision->getStatusDisplayName())
|
||||
->setIcon($revision->getStatusIcon())
|
||||
->setColor($revision->getStatusIconColor())
|
||||
->setColor($revision->getStatusTagColor())
|
||||
->setType(PHUITagView::TYPE_SHADE);
|
||||
|
||||
$view->addProperty(PHUIHeaderView::PROPERTY_STATUS, $status_tag);
|
||||
|
||||
// If the revision is in a status other than "Draft", but not broadcasting,
|
||||
// add an additional "Draft" tag to the header to make it clear that this
|
||||
// revision hasn't promoted yet.
|
||||
if (!$revision->getShouldBroadcast() && !$revision->isDraft()) {
|
||||
$draft_status = DifferentialRevisionStatus::newForStatus(
|
||||
DifferentialRevisionStatus::DRAFT);
|
||||
|
||||
$draft_tag = id(new PHUITagView())
|
||||
->setName($draft_status->getDisplayName())
|
||||
->setIcon($draft_status->getIcon())
|
||||
->setColor($draft_status->getTagColor())
|
||||
->setType(PHUITagView::TYPE_SHADE);
|
||||
|
||||
$view->addTag($draft_tag);
|
||||
}
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
|
@ -853,17 +919,11 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
|||
$header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Recent Similar Revisions'));
|
||||
|
||||
$view = id(new DifferentialRevisionListView())
|
||||
return id(new DifferentialRevisionListView())
|
||||
->setViewer($viewer)
|
||||
->setRevisions($revisions)
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->setNoBox(true)
|
||||
->setUser($viewer);
|
||||
|
||||
$phids = $view->getRequiredHandlePHIDs();
|
||||
$handles = $this->loadViewerHandles($phids);
|
||||
$view->setHandles($handles);
|
||||
|
||||
return $view;
|
||||
->setNoBox(true);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ final class DifferentialDraftField
|
|||
);
|
||||
$blocking_map = array_fuse($blocking_map);
|
||||
|
||||
$builds = $revision->loadActiveBuilds($viewer);
|
||||
$builds = $revision->loadImpactfulBuilds($viewer);
|
||||
|
||||
$waiting = array();
|
||||
$blocking = array();
|
||||
|
@ -101,7 +101,7 @@ final class DifferentialDraftField
|
|||
public function getWarningsForDetailView() {
|
||||
$revision = $this->getObject();
|
||||
|
||||
if (!$revision->isDraft()) {
|
||||
if ($revision->getShouldBroadcast()) {
|
||||
return array();
|
||||
}
|
||||
|
||||
|
|
|
@ -7,10 +7,10 @@ final class DifferentialTransactionEditor
|
|||
private $isCloseByCommit;
|
||||
private $repositoryPHIDOverride = false;
|
||||
private $didExpandInlineState = false;
|
||||
private $hasReviewTransaction = false;
|
||||
private $affectedPaths;
|
||||
private $firstBroadcast = false;
|
||||
private $wasDraft = false;
|
||||
private $wasBroadcasting;
|
||||
private $isDraftDemotion;
|
||||
|
||||
public function getEditorApplicationClass() {
|
||||
return 'PhabricatorDifferentialApplication';
|
||||
|
@ -127,17 +127,15 @@ final class DifferentialTransactionEditor
|
|||
// built it for us so we don't need to expand it again.
|
||||
$this->didExpandInlineState = true;
|
||||
break;
|
||||
case DifferentialRevisionAcceptTransaction::TRANSACTIONTYPE:
|
||||
case DifferentialRevisionRejectTransaction::TRANSACTIONTYPE:
|
||||
case DifferentialRevisionResignTransaction::TRANSACTIONTYPE:
|
||||
// If we have a review transaction, we'll skip marking the user
|
||||
// as "Commented" later. This should get cleaner after T10967.
|
||||
$this->hasReviewTransaction = true;
|
||||
case DifferentialRevisionPlanChangesTransaction::TRANSACTIONTYPE:
|
||||
if ($xaction->getMetadataValue('draft.demote')) {
|
||||
$this->isDraftDemotion = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->wasDraft = $object->isDraft();
|
||||
$this->wasBroadcasting = $object->getShouldBroadcast();
|
||||
|
||||
return parent::expandTransactions($object, $xactions);
|
||||
}
|
||||
|
@ -487,7 +485,7 @@ final class DifferentialTransactionEditor
|
|||
PhabricatorLiskDAO $object,
|
||||
array $xactions) {
|
||||
|
||||
if (!$object->shouldBroadcast()) {
|
||||
if (!$object->getShouldBroadcast()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -497,27 +495,42 @@ final class DifferentialTransactionEditor
|
|||
protected function shouldSendMail(
|
||||
PhabricatorLiskDAO $object,
|
||||
array $xactions) {
|
||||
|
||||
if (!$object->shouldBroadcast()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||
$this->requireReviewers($object);
|
||||
if ($object->getShouldBroadcast()) {
|
||||
$this->requireReviewers($object);
|
||||
|
||||
$phids = array();
|
||||
$phids[] = $object->getAuthorPHID();
|
||||
foreach ($object->getReviewers() as $reviewer) {
|
||||
if ($reviewer->isResigned()) {
|
||||
continue;
|
||||
$phids = array();
|
||||
$phids[] = $object->getAuthorPHID();
|
||||
foreach ($object->getReviewers() as $reviewer) {
|
||||
if ($reviewer->isResigned()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$phids[] = $reviewer->getReviewerPHID();
|
||||
}
|
||||
|
||||
$phids[] = $reviewer->getReviewerPHID();
|
||||
return $phids;
|
||||
}
|
||||
return $phids;
|
||||
|
||||
// If we're demoting a draft after a build failure, just notify the author.
|
||||
if ($this->isDraftDemotion) {
|
||||
$author_phid = $object->getAuthorPHID();
|
||||
return array(
|
||||
$author_phid,
|
||||
);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function getMailCC(PhabricatorLiskDAO $object) {
|
||||
if (!$object->getShouldBroadcast()) {
|
||||
return array();
|
||||
}
|
||||
|
||||
return parent::getMailCC($object);
|
||||
}
|
||||
|
||||
protected function newMailUnexpandablePHIDs(PhabricatorLiskDAO $object) {
|
||||
|
@ -555,7 +568,7 @@ final class DifferentialTransactionEditor
|
|||
|
||||
if ($show_lines) {
|
||||
$count = new PhutilNumber($object->getLineCount());
|
||||
$action = pht('%s, %s line(s)', $action, $count);
|
||||
$action = pht('%s] [%s', $action, $object->getRevisionScaleGlyphs());
|
||||
}
|
||||
|
||||
return $action;
|
||||
|
@ -1152,7 +1165,7 @@ final class DifferentialTransactionEditor
|
|||
|
||||
// If the object is still a draft, prevent "Send me an email" and other
|
||||
// similar rules from acting yet.
|
||||
if (!$object->shouldBroadcast()) {
|
||||
if (!$object->getShouldBroadcast()) {
|
||||
$adapter->setForbiddenAction(
|
||||
HeraldMailableState::STATECONST,
|
||||
DifferentialHeraldStateReasons::REASON_DRAFT);
|
||||
|
@ -1408,12 +1421,14 @@ final class DifferentialTransactionEditor
|
|||
return array(
|
||||
'changedPriorToCommitURI' => $this->changedPriorToCommitURI,
|
||||
'firstBroadcast' => $this->firstBroadcast,
|
||||
'isDraftDemotion' => $this->isDraftDemotion,
|
||||
);
|
||||
}
|
||||
|
||||
protected function loadCustomWorkerState(array $state) {
|
||||
$this->changedPriorToCommitURI = idx($state, 'changedPriorToCommitURI');
|
||||
$this->firstBroadcast = idx($state, 'firstBroadcast');
|
||||
$this->isDraftDemotion = idx($state, 'isDraftDemotion');
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -1539,8 +1554,12 @@ final class DifferentialTransactionEditor
|
|||
}
|
||||
|
||||
if ($object->isDraft() && $auto_undraft) {
|
||||
$active_builds = $this->hasActiveBuilds($object);
|
||||
if (!$active_builds) {
|
||||
$status = $this->loadCompletedBuildableStatus($object);
|
||||
|
||||
$is_passed = ($status === HarbormasterBuildableStatus::STATUS_PASSED);
|
||||
$is_failed = ($status === HarbormasterBuildableStatus::STATUS_FAILED);
|
||||
|
||||
if ($is_passed) {
|
||||
// When Harbormaster moves a revision out of the draft state, we
|
||||
// attribute the action to the revision author since this is more
|
||||
// natural and more useful.
|
||||
|
@ -1572,6 +1591,22 @@ final class DifferentialTransactionEditor
|
|||
// batch of transactions finishes so that Herald can fire on the new
|
||||
// revision state. See T13027 for discussion.
|
||||
$this->queueTransaction($xaction);
|
||||
} else if ($is_failed) {
|
||||
// When demoting a revision, we act as "Harbormaster" instead of
|
||||
// the author since this feels a little more natural.
|
||||
$harbormaster_phid = id(new PhabricatorHarbormasterApplication())
|
||||
->getPHID();
|
||||
|
||||
$xaction = $object->getApplicationTransactionTemplate()
|
||||
->setAuthorPHID($harbormaster_phid)
|
||||
->setMetadataValue('draft.demote', true)
|
||||
->setTransactionType(
|
||||
DifferentialRevisionPlanChangesTransaction::TRANSACTIONTYPE)
|
||||
->setNewValue(true);
|
||||
|
||||
$this->queueTransaction($xaction);
|
||||
|
||||
// TODO: Notify the author (only) that we did this.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1587,32 +1622,24 @@ final class DifferentialTransactionEditor
|
|||
// email so the mail gets enriched with "SUMMARY" and "TEST PLAN".
|
||||
|
||||
$is_new = $this->getIsNewObject();
|
||||
$was_draft = $this->wasDraft;
|
||||
$was_broadcasting = $this->wasBroadcasting;
|
||||
|
||||
if (!$object->isDraft() && ($was_draft || $is_new)) {
|
||||
if (!$object->getHasBroadcast()) {
|
||||
if ($object->getShouldBroadcast()) {
|
||||
if (!$was_broadcasting || $is_new) {
|
||||
// Mark this as the first broadcast we're sending about the revision
|
||||
// so mail can generate specially.
|
||||
$this->firstBroadcast = true;
|
||||
|
||||
$object
|
||||
->setHasBroadcast(true)
|
||||
->save();
|
||||
}
|
||||
}
|
||||
|
||||
return $xactions;
|
||||
}
|
||||
|
||||
private function hasActiveBuilds($object) {
|
||||
private function loadCompletedBuildableStatus(
|
||||
DifferentialRevision $revision) {
|
||||
$viewer = $this->requireActor();
|
||||
|
||||
$builds = $object->loadActiveBuilds($viewer);
|
||||
if (!$builds) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
$builds = $revision->loadImpactfulBuilds($viewer);
|
||||
return $revision->newBuildableStatusForBuilds($builds);
|
||||
}
|
||||
|
||||
private function requireReviewers(DifferentialRevision $revision) {
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialBuildableEngine
|
||||
extends HarbormasterBuildableEngine {
|
||||
|
||||
protected function getPublishableObject() {
|
||||
$object = $this->getObject();
|
||||
|
||||
if ($object instanceof DifferentialDiff) {
|
||||
return $object->getRevision();
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
public function publishBuildable(
|
||||
HarbormasterBuildable $old,
|
||||
HarbormasterBuildable $new) {
|
||||
|
||||
// If we're publishing to a diff that is not actually attached to a
|
||||
// revision, we have nothing to publish to, so just bail out.
|
||||
$revision = $this->getPublishableObject();
|
||||
if (!$revision) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't publish manual buildables.
|
||||
if ($new->getIsManualBuildable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't publish anything if the buildable is still building. Differential
|
||||
// treats more buildables as "building" than Harbormaster does, but the
|
||||
// Differential definition is a superset of the Harbormaster definition.
|
||||
if ($new->isBuilding()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$old_status = $revision->getBuildableStatus($new->getPHID());
|
||||
$new_status = $revision->newBuildableStatus($viewer, $new->getPHID());
|
||||
if ($old_status === $new_status) {
|
||||
return;
|
||||
}
|
||||
|
||||
$buildable_type = DifferentialRevisionBuildableTransaction::TRANSACTIONTYPE;
|
||||
|
||||
$xaction = $this->newTransaction()
|
||||
->setMetadataValue('harbormaster:buildablePHID', $new->getPHID())
|
||||
->setTransactionType($buildable_type)
|
||||
->setNewValue($new_status);
|
||||
|
||||
$this->applyTransactions(array($xaction));
|
||||
}
|
||||
|
||||
}
|
|
@ -41,19 +41,12 @@ final class DifferentialChangesetQuery
|
|||
}
|
||||
}
|
||||
|
||||
public function newResultObject() {
|
||||
return new DifferentialChangeset();
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
$table = new DifferentialChangeset();
|
||||
$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 $changesets) {
|
||||
|
@ -124,26 +117,24 @@ final class DifferentialChangesetQuery
|
|||
return $changesets;
|
||||
}
|
||||
|
||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||
$where = array();
|
||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$where = parent::buildWhereClauseParts($conn);
|
||||
|
||||
if ($this->diffs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
$conn,
|
||||
'diffID IN (%Ld)',
|
||||
mpull($this->diffs, 'getID'));
|
||||
}
|
||||
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
$conn,
|
||||
'id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
$where[] = $this->buildPagingClause($conn_r);
|
||||
|
||||
return $this->formatWhereClause($where);
|
||||
return $where;
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialChangesetSearchEngine
|
||||
extends PhabricatorApplicationSearchEngine {
|
||||
|
||||
private $diff;
|
||||
|
||||
public function setDiff(DifferentialDiff $diff) {
|
||||
$this->diff = $diff;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDiff() {
|
||||
return $this->diff;
|
||||
}
|
||||
|
||||
public function getResultTypeDescription() {
|
||||
return pht('Differential Changesets');
|
||||
}
|
||||
|
||||
public function getApplicationClassName() {
|
||||
return 'PhabricatorDifferentialApplication';
|
||||
}
|
||||
|
||||
public function newQuery() {
|
||||
$query = id(new DifferentialChangesetQuery());
|
||||
|
||||
if ($this->diff) {
|
||||
$query->withDiffs(array($this->diff));
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function buildQueryFromParameters(array $map) {
|
||||
$query = $this->newQuery();
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function buildCustomSearchFields() {
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function getURI($path) {
|
||||
$diff = $this->getDiff();
|
||||
if ($diff) {
|
||||
return '/differential/diff/'.$diff->getID().'/changesets/'.$path;
|
||||
}
|
||||
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
protected function getBuiltinQueryNames() {
|
||||
$names = array();
|
||||
$names['all'] = pht('All Changesets');
|
||||
return $names;
|
||||
}
|
||||
|
||||
public function buildSavedQueryFromBuiltin($query_key) {
|
||||
$query = $this->newSavedQuery();
|
||||
$query->setQueryKey($query_key);
|
||||
|
||||
$viewer = $this->requireViewer();
|
||||
|
||||
switch ($query_key) {
|
||||
case 'all':
|
||||
return $query->setParameter('order', 'oldest');
|
||||
}
|
||||
|
||||
return parent::buildSavedQueryFromBuiltin($query_key);
|
||||
}
|
||||
|
||||
protected function renderResultList(
|
||||
array $changesets,
|
||||
PhabricatorSavedQuery $query,
|
||||
array $handles) {
|
||||
|
||||
assert_instances_of($changesets, 'DifferentialChangeset');
|
||||
$viewer = $this->requireViewer();
|
||||
|
||||
$rows = array();
|
||||
foreach ($changesets as $changeset) {
|
||||
$link = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/differential/changeset/?ref='.$changeset->getID(),
|
||||
),
|
||||
$changeset->getDisplayFilename());
|
||||
|
||||
$type = $changeset->getChangeType();
|
||||
|
||||
$title = DifferentialChangeType::getFullNameForChangeType($type);
|
||||
|
||||
$add_lines = $changeset->getAddLines();
|
||||
if (!$add_lines) {
|
||||
$add_lines = null;
|
||||
} else {
|
||||
$add_lines = '+'.$add_lines;
|
||||
}
|
||||
|
||||
$rem_lines = $changeset->getDelLines();
|
||||
if (!$rem_lines) {
|
||||
$rem_lines = null;
|
||||
} else {
|
||||
$rem_lines = '-'.$rem_lines;
|
||||
}
|
||||
|
||||
$rows[] = array(
|
||||
$changeset->newFileTreeIcon(),
|
||||
$title,
|
||||
$link,
|
||||
);
|
||||
}
|
||||
|
||||
$table = id(new AphrontTableView($rows))
|
||||
->setHeaders(
|
||||
array(
|
||||
null,
|
||||
pht('Change'),
|
||||
pht('Path'),
|
||||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
null,
|
||||
null,
|
||||
'pri wide',
|
||||
));
|
||||
|
||||
return id(new PhabricatorApplicationSearchResultView())
|
||||
->setTable($table);
|
||||
}
|
||||
|
||||
}
|
|
@ -148,7 +148,7 @@ final class DifferentialRevisionSearchEngine
|
|||
|
||||
$viewer = $this->requireViewer();
|
||||
$template = id(new DifferentialRevisionListView())
|
||||
->setUser($viewer)
|
||||
->setViewer($viewer)
|
||||
->setNoBox($this->isPanelContext());
|
||||
|
||||
$bucket = $this->getResultBucket($query);
|
||||
|
@ -176,28 +176,16 @@ final class DifferentialRevisionSearchEngine
|
|||
}
|
||||
} else {
|
||||
$views[] = id(clone $template)
|
||||
->setRevisions($revisions)
|
||||
->setHandles(array());
|
||||
->setRevisions($revisions);
|
||||
}
|
||||
|
||||
if (!$views) {
|
||||
$views[] = id(new DifferentialRevisionListView())
|
||||
->setUser($viewer)
|
||||
->setViewer($viewer)
|
||||
->setNoDataString(pht('No revisions found.'));
|
||||
}
|
||||
|
||||
$phids = array_mergev(mpull($views, 'getRequiredHandlePHIDs'));
|
||||
if ($phids) {
|
||||
$handles = id(new PhabricatorHandleQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs($phids)
|
||||
->execute();
|
||||
} else {
|
||||
$handles = array();
|
||||
}
|
||||
|
||||
foreach ($views as $view) {
|
||||
$view->setHandles($handles);
|
||||
$view->setUnlandedDependencies($unlanded);
|
||||
}
|
||||
|
||||
|
|
|
@ -509,10 +509,6 @@ final class DifferentialDiff
|
|||
return null;
|
||||
}
|
||||
|
||||
public function getHarbormasterPublishablePHID() {
|
||||
return $this->getHarbormasterContainerPHID();
|
||||
}
|
||||
|
||||
public function getBuildVariables() {
|
||||
$results = array();
|
||||
|
||||
|
@ -557,6 +553,10 @@ final class DifferentialDiff
|
|||
);
|
||||
}
|
||||
|
||||
public function newBuildableEngine() {
|
||||
return new DifferentialBuildableEngine();
|
||||
}
|
||||
|
||||
|
||||
/* -( HarbormasterCircleCIBuildableInterface )----------------------------- */
|
||||
|
||||
|
|
|
@ -59,9 +59,10 @@ final class DifferentialRevision extends DifferentialDAO
|
|||
|
||||
const PROPERTY_CLOSED_FROM_ACCEPTED = 'wasAcceptedBeforeClose';
|
||||
const PROPERTY_DRAFT_HOLD = 'draft.hold';
|
||||
const PROPERTY_HAS_BROADCAST = 'draft.broadcast';
|
||||
const PROPERTY_SHOULD_BROADCAST = 'draft.broadcast';
|
||||
const PROPERTY_LINES_ADDED = 'lines.added';
|
||||
const PROPERTY_LINES_REMOVED = 'lines.removed';
|
||||
const PROPERTY_BUILDABLES = 'buildables';
|
||||
|
||||
public static function initializeNewRevision(PhabricatorUser $actor) {
|
||||
$app = id(new PhabricatorApplicationQuery())
|
||||
|
@ -74,8 +75,10 @@ final class DifferentialRevision extends DifferentialDAO
|
|||
|
||||
if (PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) {
|
||||
$initial_state = DifferentialRevisionStatus::DRAFT;
|
||||
$should_broadcast = false;
|
||||
} else {
|
||||
$initial_state = DifferentialRevisionStatus::NEEDS_REVIEW;
|
||||
$should_broadcast = true;
|
||||
}
|
||||
|
||||
return id(new DifferentialRevision())
|
||||
|
@ -84,7 +87,8 @@ final class DifferentialRevision extends DifferentialDAO
|
|||
->attachRepository(null)
|
||||
->attachActiveDiff(null)
|
||||
->attachReviewers(array())
|
||||
->setModernRevisionStatus($initial_state);
|
||||
->setModernRevisionStatus($initial_state)
|
||||
->setShouldBroadcast($should_broadcast);
|
||||
}
|
||||
|
||||
protected function getConfiguration() {
|
||||
|
@ -675,6 +679,10 @@ final class DifferentialRevision extends DifferentialDAO
|
|||
return $this->getStatusObject()->getIconColor();
|
||||
}
|
||||
|
||||
public function getStatusTagColor() {
|
||||
return $this->getStatusObject()->getTagColor();
|
||||
}
|
||||
|
||||
public function getStatusObject() {
|
||||
$status = $this->getStatus();
|
||||
return DifferentialRevisionStatus::newForStatus($status);
|
||||
|
@ -700,14 +708,6 @@ final class DifferentialRevision extends DifferentialDAO
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function shouldBroadcast() {
|
||||
if (!$this->isDraft()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getHoldAsDraft() {
|
||||
return $this->getProperty(self::PROPERTY_DRAFT_HOLD, false);
|
||||
}
|
||||
|
@ -716,12 +716,14 @@ final class DifferentialRevision extends DifferentialDAO
|
|||
return $this->setProperty(self::PROPERTY_DRAFT_HOLD, $hold);
|
||||
}
|
||||
|
||||
public function getHasBroadcast() {
|
||||
return $this->getProperty(self::PROPERTY_HAS_BROADCAST, false);
|
||||
public function getShouldBroadcast() {
|
||||
return $this->getProperty(self::PROPERTY_SHOULD_BROADCAST, true);
|
||||
}
|
||||
|
||||
public function setHasBroadcast($has_broadcast) {
|
||||
return $this->setProperty(self::PROPERTY_HAS_BROADCAST, $has_broadcast);
|
||||
public function setShouldBroadcast($should_broadcast) {
|
||||
return $this->setProperty(
|
||||
self::PROPERTY_SHOULD_BROADCAST,
|
||||
$should_broadcast);
|
||||
}
|
||||
|
||||
public function setAddedLineCount($count) {
|
||||
|
@ -740,7 +742,118 @@ final class DifferentialRevision extends DifferentialDAO
|
|||
return $this->getProperty(self::PROPERTY_LINES_REMOVED);
|
||||
}
|
||||
|
||||
public function loadActiveBuilds(PhabricatorUser $viewer) {
|
||||
public function hasLineCounts() {
|
||||
// This data was not populated on older revisions, so it may not be
|
||||
// present on all revisions.
|
||||
return isset($this->properties[self::PROPERTY_LINES_ADDED]);
|
||||
}
|
||||
|
||||
public function getRevisionScaleGlyphs() {
|
||||
$add = $this->getAddedLineCount();
|
||||
$rem = $this->getRemovedLineCount();
|
||||
$all = ($add + $rem);
|
||||
|
||||
if (!$all) {
|
||||
return ' ';
|
||||
}
|
||||
|
||||
$map = array(
|
||||
20 => 2,
|
||||
50 => 3,
|
||||
150 => 4,
|
||||
375 => 5,
|
||||
1000 => 6,
|
||||
2500 => 7,
|
||||
);
|
||||
|
||||
$n = 1;
|
||||
foreach ($map as $size => $count) {
|
||||
if ($size <= $all) {
|
||||
$n = $count;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$add_n = (int)ceil(($add / $all) * $n);
|
||||
$rem_n = (int)ceil(($rem / $all) * $n);
|
||||
|
||||
while ($add_n + $rem_n > $n) {
|
||||
if ($add_n > 1) {
|
||||
$add_n--;
|
||||
} else {
|
||||
$rem_n--;
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
str_repeat('+', $add_n).
|
||||
str_repeat('-', $rem_n).
|
||||
str_repeat(' ', (7 - $n));
|
||||
}
|
||||
|
||||
public function getBuildableStatus($phid) {
|
||||
$buildables = $this->getProperty(self::PROPERTY_BUILDABLES);
|
||||
if (!is_array($buildables)) {
|
||||
$buildables = array();
|
||||
}
|
||||
|
||||
$buildable = idx($buildables, $phid);
|
||||
if (!is_array($buildable)) {
|
||||
$buildable = array();
|
||||
}
|
||||
|
||||
return idx($buildable, 'status');
|
||||
}
|
||||
|
||||
public function setBuildableStatus($phid, $status) {
|
||||
$buildables = $this->getProperty(self::PROPERTY_BUILDABLES);
|
||||
if (!is_array($buildables)) {
|
||||
$buildables = array();
|
||||
}
|
||||
|
||||
$buildable = idx($buildables, $phid);
|
||||
if (!is_array($buildable)) {
|
||||
$buildable = array();
|
||||
}
|
||||
|
||||
$buildable['status'] = $status;
|
||||
|
||||
$buildables[$phid] = $buildable;
|
||||
|
||||
return $this->setProperty(self::PROPERTY_BUILDABLES, $buildables);
|
||||
}
|
||||
|
||||
public function newBuildableStatus(PhabricatorUser $viewer, $phid) {
|
||||
// For Differential, we're ignoring autobuilds (local lint and unit)
|
||||
// when computing build status. Differential only cares about remote
|
||||
// builds when making publishing and undrafting decisions.
|
||||
|
||||
$builds = $this->loadImpactfulBuildsForBuildablePHIDs(
|
||||
$viewer,
|
||||
array($phid));
|
||||
|
||||
return $this->newBuildableStatusForBuilds($builds);
|
||||
}
|
||||
|
||||
public function newBuildableStatusForBuilds(array $builds) {
|
||||
// If we have nothing but passing builds, the buildable passes.
|
||||
if (!$builds) {
|
||||
return HarbormasterBuildableStatus::STATUS_PASSED;
|
||||
}
|
||||
|
||||
// If we have any completed, non-passing builds, the buildable fails.
|
||||
foreach ($builds as $build) {
|
||||
if ($build->isComplete()) {
|
||||
return HarbormasterBuildableStatus::STATUS_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we're still waiting for the build to pass or fail.
|
||||
return null;
|
||||
}
|
||||
|
||||
public function loadImpactfulBuilds(PhabricatorUser $viewer) {
|
||||
$diff = $this->getActiveDiff();
|
||||
|
||||
// NOTE: We can't use `withContainerPHIDs()` here because the container
|
||||
|
@ -754,9 +867,18 @@ final class DifferentialRevision extends DifferentialDAO
|
|||
return array();
|
||||
}
|
||||
|
||||
return $this->loadImpactfulBuildsForBuildablePHIDs(
|
||||
$viewer,
|
||||
mpull($buildables, 'getPHID'));
|
||||
}
|
||||
|
||||
private function loadImpactfulBuildsForBuildablePHIDs(
|
||||
PhabricatorUser $viewer,
|
||||
array $phids) {
|
||||
|
||||
return id(new HarbormasterBuildQuery())
|
||||
->setViewer($viewer)
|
||||
->withBuildablePHIDs(mpull($buildables, 'getPHID'))
|
||||
->withBuildablePHIDs($phids)
|
||||
->withAutobuilds(false)
|
||||
->withBuildStatuses(
|
||||
array(
|
||||
|
@ -788,10 +910,6 @@ final class DifferentialRevision extends DifferentialDAO
|
|||
return $this->getPHID();
|
||||
}
|
||||
|
||||
public function getHarbormasterPublishablePHID() {
|
||||
return $this->getPHID();
|
||||
}
|
||||
|
||||
public function getBuildVariables() {
|
||||
return array();
|
||||
}
|
||||
|
@ -800,6 +918,10 @@ final class DifferentialRevision extends DifferentialDAO
|
|||
return array();
|
||||
}
|
||||
|
||||
public function newBuildableEngine() {
|
||||
return new DifferentialBuildableEngine();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorSubscribableInterface )----------------------------------- */
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
final class DifferentialRevisionListView extends AphrontView {
|
||||
|
||||
private $revisions = array();
|
||||
private $handles;
|
||||
private $header;
|
||||
private $noDataString;
|
||||
private $noBox;
|
||||
|
@ -48,32 +47,43 @@ final class DifferentialRevisionListView extends AphrontView {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function getRequiredHandlePHIDs() {
|
||||
$phids = array();
|
||||
foreach ($this->revisions as $revision) {
|
||||
$phids[] = array($revision->getAuthorPHID());
|
||||
$phids[] = $revision->getReviewerPHIDs();
|
||||
}
|
||||
return array_mergev($phids);
|
||||
}
|
||||
|
||||
public function setHandles(array $handles) {
|
||||
assert_instances_of($handles, 'PhabricatorObjectHandle');
|
||||
$this->handles = $handles;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$this->initBehavior('phabricator-tooltips', array());
|
||||
$this->requireResource('aphront-tooltip-css');
|
||||
|
||||
$list = new PHUIObjectItemListView();
|
||||
$reviewer_limit = 7;
|
||||
|
||||
foreach ($this->revisions as $revision) {
|
||||
$reviewer_phids = array();
|
||||
$reviewer_more = array();
|
||||
$handle_phids = array();
|
||||
foreach ($this->revisions as $key => $revision) {
|
||||
$reviewers = $revision->getReviewers();
|
||||
if (count($reviewers) > $reviewer_limit) {
|
||||
$reviewers = array_slice($reviewers, 0, $reviewer_limit);
|
||||
$reviewer_more[$key] = true;
|
||||
} else {
|
||||
$reviewer_more[$key] = false;
|
||||
}
|
||||
|
||||
$phids = mpull($reviewers, 'getReviewerPHID');
|
||||
|
||||
$reviewer_phids[$key] = $phids;
|
||||
foreach ($phids as $phid) {
|
||||
$handle_phids[$phid] = $phid;
|
||||
}
|
||||
|
||||
$author_phid = $revision->getAuthorPHID();
|
||||
$handle_phids[$author_phid] = $author_phid;
|
||||
}
|
||||
|
||||
$handles = $viewer->loadHandles($handle_phids);
|
||||
|
||||
$list = new PHUIObjectItemListView();
|
||||
foreach ($this->revisions as $key => $revision) {
|
||||
$item = id(new PHUIObjectItemView())
|
||||
->setUser($viewer);
|
||||
->setViewer($viewer);
|
||||
|
||||
$icons = array();
|
||||
|
||||
|
@ -89,21 +99,22 @@ final class DifferentialRevisionListView extends AphrontView {
|
|||
'');
|
||||
}
|
||||
|
||||
if ($revision->getHasDraft($viewer)) {
|
||||
$icons['draft'] = true;
|
||||
}
|
||||
|
||||
$modified = $revision->getDateModified();
|
||||
|
||||
if (isset($icons['flag'])) {
|
||||
$item->addHeadIcon($icons['flag']);
|
||||
}
|
||||
|
||||
$item->setObjectName('D'.$revision->getID());
|
||||
$item->setObjectName($revision->getMonogram());
|
||||
$item->setHeader($revision->getTitle());
|
||||
$item->setHref('/D'.$revision->getID());
|
||||
$item->setHref($revision->getURI());
|
||||
|
||||
if (isset($icons['draft'])) {
|
||||
$size = $this->renderRevisionSize($revision);
|
||||
if ($size !== null) {
|
||||
$item->addAttribute($size);
|
||||
}
|
||||
|
||||
if ($revision->getHasDraft($viewer)) {
|
||||
$draft = id(new PHUIIconView())
|
||||
->setIcon('fa-comment yellow')
|
||||
->addSigil('has-tooltip')
|
||||
|
@ -114,8 +125,7 @@ final class DifferentialRevisionListView extends AphrontView {
|
|||
$item->addAttribute($draft);
|
||||
}
|
||||
|
||||
// Author
|
||||
$author_handle = $this->handles[$revision->getAuthorPHID()];
|
||||
$author_handle = $handles[$revision->getAuthorPHID()];
|
||||
$item->addByline(pht('Author: %s', $author_handle->renderLink()));
|
||||
|
||||
$unlanded = idx($this->unlandedDependencies, $phid);
|
||||
|
@ -128,17 +138,26 @@ final class DifferentialRevisionListView extends AphrontView {
|
|||
));
|
||||
}
|
||||
|
||||
$reviewers = array();
|
||||
foreach ($revision->getReviewerPHIDs() as $reviewer) {
|
||||
$reviewers[] = $this->handles[$reviewer]->renderLink();
|
||||
}
|
||||
if (!$reviewers) {
|
||||
$reviewers = phutil_tag('em', array(), pht('None'));
|
||||
$more = null;
|
||||
if ($reviewer_more[$key]) {
|
||||
$more = pht(', ...');
|
||||
} else {
|
||||
$reviewers = phutil_implode_html(', ', $reviewers);
|
||||
$more = null;
|
||||
}
|
||||
|
||||
if ($reviewer_phids[$key]) {
|
||||
$item->addAttribute(
|
||||
array(
|
||||
pht('Reviewers:'),
|
||||
' ',
|
||||
$viewer->renderHandleList($reviewer_phids[$key])
|
||||
->setAsInline(true),
|
||||
$more,
|
||||
));
|
||||
} else {
|
||||
$item->addAttribute(phutil_tag('em', array(), pht('No Reviewers')));
|
||||
}
|
||||
|
||||
$item->addAttribute(pht('Reviewers: %s', $reviewers));
|
||||
$item->setEpoch($revision->getDateModified());
|
||||
|
||||
if ($revision->isClosed()) {
|
||||
|
@ -176,4 +195,59 @@ final class DifferentialRevisionListView extends AphrontView {
|
|||
return $list;
|
||||
}
|
||||
|
||||
private function renderRevisionSize(DifferentialRevision $revision) {
|
||||
if (!$revision->hasLineCounts()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$size = array();
|
||||
|
||||
$glyphs = $revision->getRevisionScaleGlyphs();
|
||||
$plus_count = 0;
|
||||
for ($ii = 0; $ii < 7; $ii++) {
|
||||
$c = $glyphs[$ii];
|
||||
|
||||
switch ($c) {
|
||||
case '+':
|
||||
$size[] = id(new PHUIIconView())
|
||||
->setIcon('fa-plus');
|
||||
$plus_count++;
|
||||
break;
|
||||
case '-':
|
||||
$size[] = id(new PHUIIconView())
|
||||
->setIcon('fa-minus');
|
||||
break;
|
||||
default:
|
||||
$size[] = id(new PHUIIconView())
|
||||
->setIcon('fa-square-o invisible');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$n = $revision->getAddedLineCount() + $revision->getRemovedLineCount();
|
||||
|
||||
$classes = array();
|
||||
$classes[] = 'differential-revision-size';
|
||||
|
||||
if ($plus_count <= 1) {
|
||||
$classes[] = 'differential-revision-small';
|
||||
}
|
||||
|
||||
if ($plus_count >= 4) {
|
||||
$classes[] = 'differential-revision-large';
|
||||
}
|
||||
|
||||
return javelin_tag(
|
||||
'span',
|
||||
array(
|
||||
'class' => implode(' ', $classes),
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => pht('%s Lines', new PhutilNumber($n)),
|
||||
'align' => 'E',
|
||||
),
|
||||
),
|
||||
$size);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -147,10 +147,23 @@ abstract class DifferentialRevisionActionTransaction
|
|||
$actor = $this->getActor();
|
||||
|
||||
$action_exception = null;
|
||||
try {
|
||||
$this->validateAction($object, $actor);
|
||||
} catch (Exception $ex) {
|
||||
$action_exception = $ex;
|
||||
foreach ($xactions as $xaction) {
|
||||
// If this is a draft demotion action, let it skip all the normal
|
||||
// validation. This is a little hacky and should perhaps move down
|
||||
// into the actual action implementations, but currently we can not
|
||||
// apply this rule in validateAction() because it doesn't operate on
|
||||
// the actual transaction.
|
||||
if ($xaction->getMetadataValue('draft.demote')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->validateAction($object, $actor);
|
||||
} catch (Exception $ex) {
|
||||
$action_exception = $ex;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($xactions as $xaction) {
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialRevisionBuildableTransaction
|
||||
extends DifferentialRevisionTransactionType {
|
||||
|
||||
// NOTE: This uses an older constant for compatibility. We should perhaps
|
||||
// migrate these at some point.
|
||||
const TRANSACTIONTYPE = 'harbormaster:buildable';
|
||||
|
||||
public function generateNewValue($object, $value) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return $object->getBuildableStatus($this->getBuildablePHID());
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setBuildableStatus($this->getBuildablePHID(), $value);
|
||||
}
|
||||
|
||||
public function getIcon() {
|
||||
return $this->newBuildableStatus()->getIcon();
|
||||
}
|
||||
|
||||
public function getColor() {
|
||||
return $this->newBuildableStatus()->getColor();
|
||||
}
|
||||
|
||||
public function getActionName() {
|
||||
return $this->newBuildableStatus()->getActionName();
|
||||
}
|
||||
|
||||
public function shouldHideForFeed() {
|
||||
return !$this->newBuildableStatus()->isFailed();
|
||||
}
|
||||
|
||||
public function shouldHideForMail() {
|
||||
return !$this->newBuildableStatus()->isFailed();
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
$new = $this->getNewValue();
|
||||
$buildable_phid = $this->getBuildablePHID();
|
||||
|
||||
switch ($new) {
|
||||
case HarbormasterBuildableStatus::STATUS_PASSED:
|
||||
return pht(
|
||||
'%s completed remote builds in %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderHandle($buildable_phid));
|
||||
case HarbormasterBuildableStatus::STATUS_FAILED:
|
||||
return pht(
|
||||
'%s failed remote builds in %s!',
|
||||
$this->renderAuthor(),
|
||||
$this->renderHandle($buildable_phid));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getTitleForFeed() {
|
||||
$new = $this->getNewValue();
|
||||
$buildable_phid = $this->getBuildablePHID();
|
||||
|
||||
switch ($new) {
|
||||
case HarbormasterBuildableStatus::STATUS_PASSED:
|
||||
return pht(
|
||||
'%s completed remote builds in %s for %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderHandle($buildable_phid),
|
||||
$this->renderObject());
|
||||
case HarbormasterBuildableStatus::STATUS_FAILED:
|
||||
return pht(
|
||||
'%s failed remote builds in %s for %s!',
|
||||
$this->renderAuthor(),
|
||||
$this->renderHandle($buildable_phid),
|
||||
$this->renderObject());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function newBuildableStatus() {
|
||||
$new = $this->getNewValue();
|
||||
return HarbormasterBuildableStatus::newBuildableStatusObject($new);
|
||||
}
|
||||
|
||||
private function getBuildablePHID() {
|
||||
return $this->getMetadataValue('harbormaster:buildablePHID');
|
||||
}
|
||||
|
||||
}
|
|
@ -96,9 +96,16 @@ final class DifferentialRevisionPlanChangesTransaction
|
|||
}
|
||||
|
||||
public function getTitle() {
|
||||
return pht(
|
||||
'%s planned changes to this revision.',
|
||||
$this->renderAuthor());
|
||||
if ($this->isDraftDemotion()) {
|
||||
return pht(
|
||||
'%s returned this revision to the author for changes because remote '.
|
||||
'builds failed.',
|
||||
$this->renderAuthor());
|
||||
} else {
|
||||
return pht(
|
||||
'%s planned changes to this revision.',
|
||||
$this->renderAuthor());
|
||||
}
|
||||
}
|
||||
|
||||
public function getTitleForFeed() {
|
||||
|
@ -108,4 +115,8 @@ final class DifferentialRevisionPlanChangesTransaction
|
|||
$this->renderObject());
|
||||
}
|
||||
|
||||
private function isDraftDemotion() {
|
||||
return (bool)$this->getMetadataValue('draft.demote');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,8 +48,12 @@ final class DifferentialRevisionReclaimTransaction
|
|||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$status_review = DifferentialRevisionStatus::NEEDS_REVIEW;
|
||||
$object->setModernRevisionStatus($status_review);
|
||||
if ($object->getShouldBroadcast()) {
|
||||
$new_status = DifferentialRevisionStatus::NEEDS_REVIEW;
|
||||
} else {
|
||||
$new_status = DifferentialRevisionStatus::DRAFT;
|
||||
}
|
||||
$object->setModernRevisionStatus($new_status);
|
||||
}
|
||||
|
||||
protected function validateAction($object, PhabricatorUser $viewer) {
|
||||
|
|
|
@ -37,7 +37,9 @@ final class DifferentialRevisionRequestReviewTransaction
|
|||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$status_review = DifferentialRevisionStatus::NEEDS_REVIEW;
|
||||
$object->setModernRevisionStatus($status_review);
|
||||
$object
|
||||
->setModernRevisionStatus($status_review)
|
||||
->setShouldBroadcast(true);
|
||||
}
|
||||
|
||||
protected function validateAction($object, PhabricatorUser $viewer) {
|
||||
|
|
|
@ -13,8 +13,14 @@ final class DifferentialRevisionUpdateTransaction
|
|||
public function applyInternalEffects($object, $value) {
|
||||
$should_review = $this->shouldRequestReviewAfterUpdate($object);
|
||||
if ($should_review) {
|
||||
$object->setModernRevisionStatus(
|
||||
DifferentialRevisionStatus::NEEDS_REVIEW);
|
||||
// If we're updating a non-broadcasting revision, put it back in draft
|
||||
// rather than moving it directly to "Needs Review".
|
||||
if ($object->getShouldBroadcast()) {
|
||||
$new_status = DifferentialRevisionStatus::NEEDS_REVIEW;
|
||||
} else {
|
||||
$new_status = DifferentialRevisionStatus::DRAFT;
|
||||
}
|
||||
$object->setModernRevisionStatus($new_status);
|
||||
}
|
||||
|
||||
$editor = $this->getEditor();
|
||||
|
|
|
@ -1754,14 +1754,10 @@ final class DiffusionBrowseController extends DiffusionController {
|
|||
->setHeader(pht('Recently Open Revisions'));
|
||||
|
||||
$list = id(new DifferentialRevisionListView())
|
||||
->setViewer($viewer)
|
||||
->setRevisions($revisions)
|
||||
->setUser($viewer)
|
||||
->setNoBox(true);
|
||||
|
||||
$phids = $list->getRequiredHandlePHIDs();
|
||||
$handles = $this->loadViewerHandles($phids);
|
||||
$list->setHandles($handles);
|
||||
|
||||
$view = id(new PHUIObjectBoxView())
|
||||
->setHeader($header)
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionBuildableEngine
|
||||
extends HarbormasterBuildableEngine {
|
||||
|
||||
public function publishBuildable(
|
||||
HarbormasterBuildable $old,
|
||||
HarbormasterBuildable $new) {
|
||||
|
||||
// Don't publish manual buildables.
|
||||
if ($new->getIsManualBuildable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't publish anything if the buildable status has not changed. At
|
||||
// least for now, Diffusion handles buildable status exactly the same
|
||||
// way that Harbormaster does.
|
||||
$old_status = $old->getBuildableStatus();
|
||||
$new_status = $new->getBuildableStatus();
|
||||
if ($old_status === $new_status) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't publish anything if the buildable is still building.
|
||||
if ($new->isBuilding()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$xaction = $this->newTransaction()
|
||||
->setMetadataValue('harbormaster:buildablePHID', $new->getPHID())
|
||||
->setTransactionType(DiffusionCommitBuildableTransaction::TRANSACTIONTYPE)
|
||||
->setNewValue($new->getBuildableStatus());
|
||||
|
||||
$this->applyTransactions(array($xaction));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionCommitBuildableTransaction
|
||||
extends DiffusionCommitTransactionType {
|
||||
|
||||
// NOTE: This uses an older constant for compatibility. We should perhaps
|
||||
// migrate these at some point.
|
||||
const TRANSACTIONTYPE = 'harbormaster:buildable';
|
||||
|
||||
public function generateNewValue($object, $value) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getIcon() {
|
||||
return $this->newBuildableStatus()->getIcon();
|
||||
}
|
||||
|
||||
public function getColor() {
|
||||
return $this->newBuildableStatus()->getColor();
|
||||
}
|
||||
|
||||
public function getActionName() {
|
||||
return $this->newBuildableStatus()->getActionName();
|
||||
}
|
||||
|
||||
public function shouldHideForFeed() {
|
||||
return !$this->newBuildableStatus()->isFailed();
|
||||
}
|
||||
|
||||
public function shouldHideForMail() {
|
||||
return !$this->newBuildableStatus()->isFailed();
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
$new = $this->getNewValue();
|
||||
$buildable_phid = $this->getBuildablePHID();
|
||||
|
||||
switch ($new) {
|
||||
case HarbormasterBuildableStatus::STATUS_PASSED:
|
||||
return pht(
|
||||
'%s completed building %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderHandle($buildable_phid));
|
||||
case HarbormasterBuildableStatus::STATUS_FAILED:
|
||||
return pht(
|
||||
'%s failed to build %s!',
|
||||
$this->renderAuthor(),
|
||||
$this->renderHandle($buildable_phid));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getTitleForFeed() {
|
||||
$new = $this->getNewValue();
|
||||
$buildable_phid = $this->getBuildablePHID();
|
||||
|
||||
switch ($new) {
|
||||
case HarbormasterBuildableStatus::STATUS_PASSED:
|
||||
return pht(
|
||||
'%s completed building %s for %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderHandle($buildable_phid),
|
||||
$this->renderObject());
|
||||
case HarbormasterBuildableStatus::STATUS_FAILED:
|
||||
return pht(
|
||||
'%s failed to build %s for %s!',
|
||||
$this->renderAuthor(),
|
||||
$this->renderHandle($buildable_phid),
|
||||
$this->renderObject());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function newBuildableStatus() {
|
||||
$new = $this->getNewValue();
|
||||
return HarbormasterBuildableStatus::newBuildableStatusObject($new);
|
||||
}
|
||||
|
||||
private function getBuildablePHID() {
|
||||
return $this->getMetadataValue('harbormaster:buildablePHID');
|
||||
}
|
||||
|
||||
}
|
|
@ -39,6 +39,10 @@ final class HarbormasterBuildableStatus extends Phobject {
|
|||
return $this->getProperty('name');
|
||||
}
|
||||
|
||||
public function getActionName() {
|
||||
return $this->getProperty('name.action');
|
||||
}
|
||||
|
||||
public function getColor() {
|
||||
return $this->getProperty('color');
|
||||
}
|
||||
|
@ -47,6 +51,14 @@ final class HarbormasterBuildableStatus extends Phobject {
|
|||
return ($this->key === self::STATUS_PREPARING);
|
||||
}
|
||||
|
||||
public function isBuilding() {
|
||||
return ($this->key === self::STATUS_BUILDING);
|
||||
}
|
||||
|
||||
public function isFailed() {
|
||||
return ($this->key === self::STATUS_FAILED);
|
||||
}
|
||||
|
||||
public static function getOptionMap() {
|
||||
return ipull(self::getSpecifications(), 'name');
|
||||
}
|
||||
|
@ -57,21 +69,25 @@ final class HarbormasterBuildableStatus extends Phobject {
|
|||
'name' => pht('Preparing'),
|
||||
'color' => 'blue',
|
||||
'icon' => 'fa-hourglass-o',
|
||||
'name.action' => pht('Build Preparing'),
|
||||
),
|
||||
self::STATUS_BUILDING => array(
|
||||
'name' => pht('Building'),
|
||||
'color' => 'blue',
|
||||
'icon' => 'fa-chevron-circle-right',
|
||||
'name.action' => pht('Build Started'),
|
||||
),
|
||||
self::STATUS_PASSED => array(
|
||||
'name' => pht('Passed'),
|
||||
'color' => 'green',
|
||||
'icon' => 'fa-check-circle',
|
||||
'name.action' => pht('Build Passed'),
|
||||
),
|
||||
self::STATUS_FAILED => array(
|
||||
'name' => pht('Failed'),
|
||||
'color' => 'red',
|
||||
'icon' => 'fa-times-circle',
|
||||
'name.action' => pht('Build Failed'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -86,6 +102,7 @@ final class HarbormasterBuildableStatus extends Phobject {
|
|||
'name' => pht('Unknown ("%s")', $status),
|
||||
'icon' => 'fa-question-circle',
|
||||
'color' => 'bluegrey',
|
||||
'name.action' => pht('Build Status'),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -489,6 +489,8 @@ final class HarbormasterBuildEngine extends Phobject {
|
|||
}
|
||||
}
|
||||
|
||||
$old = clone $buildable;
|
||||
|
||||
// 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
|
||||
|
@ -515,8 +517,7 @@ final class HarbormasterBuildEngine extends Phobject {
|
|||
$new_status = HarbormasterBuildableStatus::STATUS_BUILDING;
|
||||
}
|
||||
|
||||
$old_status = $buildable->getBuildableStatus();
|
||||
$did_update = ($old_status != $new_status);
|
||||
$did_update = ($old->getBuildableStatus() !== $new_status);
|
||||
if ($did_update) {
|
||||
$buildable->setBuildableStatus($new_status);
|
||||
$buildable->save();
|
||||
|
@ -530,81 +531,45 @@ final class HarbormasterBuildEngine extends Phobject {
|
|||
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.
|
||||
$this->publishBuildable($old, $buildable);
|
||||
}
|
||||
|
||||
// NOTE: We only post transactions for automatic buildables, not for
|
||||
// manual ones: manual builds are test builds, whoever is doing tests
|
||||
// can look at the results themselves, and other users generally don't
|
||||
// care about the outcome.
|
||||
public function publishBuildable(
|
||||
HarbormasterBuildable $old,
|
||||
HarbormasterBuildable $new) {
|
||||
|
||||
$should_publish =
|
||||
($did_update) &&
|
||||
($new_status != HarbormasterBuildableStatus::STATUS_BUILDING) &&
|
||||
(!$buildable->getIsManualBuildable());
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
if (!$should_publish) {
|
||||
return;
|
||||
}
|
||||
// Publish the buildable. We publish buildables even if they haven't
|
||||
// changed status in Harbormaster because applications may care about
|
||||
// different things than Harbormaster does. For example, Differential
|
||||
// does not care about local lint and unit tests when deciding whether
|
||||
// a revision should move out of draft or not.
|
||||
|
||||
// NOTE: We're publishing both automatic and manual buildables. Buildable
|
||||
// objects should generally ignore manual buildables, but it's up to them
|
||||
// to decide.
|
||||
|
||||
$object = id(new PhabricatorObjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($buildable->getBuildablePHID()))
|
||||
->withPHIDs(array($new->getBuildablePHID()))
|
||||
->executeOne();
|
||||
if (!$object) {
|
||||
return;
|
||||
}
|
||||
|
||||
$publish_phid = $object->getHarbormasterPublishablePHID();
|
||||
if (!$publish_phid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($publish_phid === $object->getPHID()) {
|
||||
$publish = $object;
|
||||
} else {
|
||||
$publish = id(new PhabricatorObjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($publish_phid))
|
||||
->executeOne();
|
||||
if (!$publish) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!($publish instanceof PhabricatorApplicationTransactionInterface)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$template = $publish->getApplicationTransactionTemplate();
|
||||
if (!$template) {
|
||||
return;
|
||||
}
|
||||
|
||||
$template
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_BUILDABLE)
|
||||
->setMetadataValue(
|
||||
'harbormaster:buildablePHID',
|
||||
$buildable->getPHID())
|
||||
->setOldValue($old_status)
|
||||
->setNewValue($new_status);
|
||||
|
||||
$harbormaster_phid = id(new PhabricatorHarbormasterApplication())
|
||||
->getPHID();
|
||||
$engine = HarbormasterBuildableEngine::newForObject($object, $viewer);
|
||||
|
||||
$daemon_source = PhabricatorContentSource::newForSource(
|
||||
PhabricatorDaemonContentSource::SOURCECONST);
|
||||
|
||||
$editor = $publish->getApplicationTransactionEditor()
|
||||
->setActor($viewer)
|
||||
$harbormaster_phid = id(new PhabricatorHarbormasterApplication())
|
||||
->getPHID();
|
||||
|
||||
$engine
|
||||
->setActingAsPHID($harbormaster_phid)
|
||||
->setContentSource($daemon_source)
|
||||
->setContinueOnNoEffect(true)
|
||||
->setContinueOnMissingFields(true);
|
||||
|
||||
$editor->applyTransactions(
|
||||
$publish->getApplicationTransactionObject(),
|
||||
array($template));
|
||||
->publishBuildable($old, $new);
|
||||
}
|
||||
|
||||
private function releaseAllArtifacts(HarbormasterBuild $build) {
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
abstract class HarbormasterBuildableEngine
|
||||
extends Phobject {
|
||||
|
||||
private $viewer;
|
||||
private $actingAsPHID;
|
||||
private $contentSource;
|
||||
private $object;
|
||||
|
||||
final public function setViewer(PhabricatorUser $viewer) {
|
||||
$this->viewer = $viewer;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getViewer() {
|
||||
return $this->viewer;
|
||||
}
|
||||
|
||||
final public function setActingAsPHID($acting_as_phid) {
|
||||
$this->actingAsPHID = $acting_as_phid;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getActingAsPHID() {
|
||||
return $this->actingAsPHID;
|
||||
}
|
||||
|
||||
final public function setContentSource(
|
||||
PhabricatorContentSource $content_source) {
|
||||
$this->contentSource = $content_source;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getContentSource() {
|
||||
return $this->contentSource;
|
||||
}
|
||||
|
||||
final public function setObject(HarbormasterBuildableInterface $object) {
|
||||
$this->object = $object;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getObject() {
|
||||
return $this->object;
|
||||
}
|
||||
|
||||
protected function getPublishableObject() {
|
||||
return $this->getObject();
|
||||
}
|
||||
|
||||
public function publishBuildable(
|
||||
HarbormasterBuildable $old,
|
||||
HarbormasterBuildable $new) {
|
||||
return;
|
||||
}
|
||||
|
||||
final public static function newForObject(
|
||||
HarbormasterBuildableInterface $object,
|
||||
PhabricatorUser $viewer) {
|
||||
return $object->newBuildableEngine()
|
||||
->setViewer($viewer)
|
||||
->setObject($object);
|
||||
}
|
||||
|
||||
final protected function newEditor() {
|
||||
$publishable = $this->getPublishableObject();
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$editor = $publishable->getApplicationTransactionEditor()
|
||||
->setActor($viewer)
|
||||
->setContinueOnNoEffect(true)
|
||||
->setContinueOnMissingFields(true);
|
||||
|
||||
$acting_as_phid = $this->getActingAsPHID();
|
||||
if ($acting_as_phid !== null) {
|
||||
$editor->setActingAsPHID($acting_as_phid);
|
||||
}
|
||||
|
||||
$content_source = $this->getContentSource();
|
||||
if ($content_source !== null) {
|
||||
$editor->setContentSource($content_source);
|
||||
}
|
||||
|
||||
return $editor;
|
||||
}
|
||||
|
||||
final protected function newTransaction() {
|
||||
$publishable = $this->getPublishableObject();
|
||||
|
||||
return $publishable->getApplicationTransactionTemplate();
|
||||
}
|
||||
|
||||
final protected function applyTransactions(array $xactions) {
|
||||
$publishable = $this->getPublishableObject();
|
||||
$editor = $this->newEditor();
|
||||
|
||||
$editor->applyTransactions(
|
||||
$publishable->getApplicationTransactionObject(),
|
||||
$xactions);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -18,22 +18,9 @@ interface HarbormasterBuildableInterface {
|
|||
public function getHarbormasterBuildablePHID();
|
||||
public function getHarbormasterContainerPHID();
|
||||
|
||||
|
||||
/**
|
||||
* Get the object PHID which build status should be published to.
|
||||
*
|
||||
* In some cases (like commits), this is the object itself. In other cases,
|
||||
* it is a different object: for example, diffs publish builds to revisions.
|
||||
*
|
||||
* This method can return `null` to disable publishing.
|
||||
*
|
||||
* @return phid|null Build status updates will be published to this object's
|
||||
* transaction timeline.
|
||||
*/
|
||||
public function getHarbormasterPublishablePHID();
|
||||
|
||||
|
||||
public function getBuildVariables();
|
||||
public function getAvailableBuildVariables();
|
||||
|
||||
public function newBuildableEngine();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
|
||||
final class HarbormasterManagementPublishWorkflow
|
||||
extends HarbormasterManagementWorkflow {
|
||||
|
||||
protected function didConstruct() {
|
||||
$this
|
||||
->setName('publish')
|
||||
->setExamples(pht('**publish** __buildable__ ...'))
|
||||
->setSynopsis(
|
||||
pht(
|
||||
'Publish a buildable. This is primarily useful for developing '.
|
||||
'and debugging applications which have buildable objects.'))
|
||||
->setArguments(
|
||||
array(
|
||||
array(
|
||||
'name' => 'buildable',
|
||||
'wildcard' => true,
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
public function execute(PhutilArgumentParser $args) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$buildable_names = $args->getArg('buildable');
|
||||
if (!$buildable_names) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Name one or more buildables to publish, like "B123".'));
|
||||
}
|
||||
|
||||
$query = id(new PhabricatorObjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withNames($buildable_names);
|
||||
|
||||
$query->execute();
|
||||
|
||||
$result_map = $query->getNamedResults();
|
||||
|
||||
foreach ($buildable_names as $name) {
|
||||
if (!isset($result_map[$name])) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Argument "%s" does not name a buildable. Provide one or more '.
|
||||
'valid buildable monograms or PHIDs.',
|
||||
$name));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($result_map as $name => $result) {
|
||||
if (!($result instanceof HarbormasterBuildable)) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Object "%s" is not a HarbormasterBuildable (it is a "%s"). '.
|
||||
'Name one or more buildables to publish, like "B123".',
|
||||
get_class($result)));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($result_map as $buildable) {
|
||||
echo tsprintf(
|
||||
"%s\n",
|
||||
pht(
|
||||
'Publishing "%s"...',
|
||||
$buildable->getMonogram()));
|
||||
|
||||
// Reload the buildable to pick up builds.
|
||||
$buildable = id(new HarbormasterBuildableQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($buildable->getID()))
|
||||
->needBuilds(true)
|
||||
->executeOne();
|
||||
|
||||
$engine = id(new HarbormasterBuildEngine())
|
||||
->setViewer($viewer)
|
||||
->publishBuildable($buildable, $buildable);
|
||||
}
|
||||
|
||||
echo tsprintf(
|
||||
"%s\n",
|
||||
pht('Done.'));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -233,6 +233,10 @@ final class HarbormasterBuildable
|
|||
return $this->getBuildableStatusObject()->isPreparing();
|
||||
}
|
||||
|
||||
public function isBuilding() {
|
||||
return $this->getBuildableStatusObject()->isBuilding();
|
||||
}
|
||||
|
||||
|
||||
/* -( Messages )----------------------------------------------------------- */
|
||||
|
||||
|
@ -329,10 +333,6 @@ final class HarbormasterBuildable
|
|||
return $this->getContainerPHID();
|
||||
}
|
||||
|
||||
public function getHarbormasterPublishablePHID() {
|
||||
return $this->getBuildableObject()->getHarbormasterPublishablePHID();
|
||||
}
|
||||
|
||||
public function getBuildVariables() {
|
||||
return array();
|
||||
}
|
||||
|
@ -341,6 +341,10 @@ final class HarbormasterBuildable
|
|||
return array();
|
||||
}
|
||||
|
||||
public function newBuildableEngine() {
|
||||
return $this->getBuildableObject()->newBuildableEngine();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorDestructibleInterface )----------------------------------- */
|
||||
|
||||
|
|
|
@ -63,15 +63,11 @@ final class PhabricatorPeopleProfileRevisionsController
|
|||
->execute();
|
||||
|
||||
$list = id(new DifferentialRevisionListView())
|
||||
->setUser($viewer)
|
||||
->setViewer($viewer)
|
||||
->setNoBox(true)
|
||||
->setRevisions($revisions)
|
||||
->setNoDataString(pht('No recent revisions.'));
|
||||
|
||||
$object_phids = $list->getRequiredHandlePHIDs();
|
||||
$handles = $this->loadViewerHandles($object_phids);
|
||||
$list->setHandles($handles);
|
||||
|
||||
$view = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Recent Revisions'))
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
|
|
|
@ -517,10 +517,6 @@ final class PhabricatorRepositoryCommit
|
|||
return $this->getRepository()->getPHID();
|
||||
}
|
||||
|
||||
public function getHarbormasterPublishablePHID() {
|
||||
return $this->getPHID();
|
||||
}
|
||||
|
||||
public function getBuildVariables() {
|
||||
$results = array();
|
||||
|
||||
|
@ -549,6 +545,10 @@ final class PhabricatorRepositoryCommit
|
|||
);
|
||||
}
|
||||
|
||||
public function newBuildableEngine() {
|
||||
return new DiffusionBuildableEngine();
|
||||
}
|
||||
|
||||
|
||||
/* -( HarbormasterCircleCIBuildableInterface )----------------------------- */
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ final class PhabricatorTransactions extends Phobject {
|
|||
const TYPE_JOIN_POLICY = 'core:join-policy';
|
||||
const TYPE_EDGE = 'core:edge';
|
||||
const TYPE_CUSTOMFIELD = 'core:customfield';
|
||||
const TYPE_BUILDABLE = 'harbormaster:buildable';
|
||||
const TYPE_TOKEN = 'token:give';
|
||||
const TYPE_INLINESTATE = 'core:inlinestate';
|
||||
const TYPE_SPACE = 'core:space';
|
||||
|
|
|
@ -313,10 +313,6 @@ abstract class PhabricatorApplicationTransactionEditor
|
|||
$types[] = PhabricatorTransactions::TYPE_CUSTOMFIELD;
|
||||
}
|
||||
|
||||
if ($this->object instanceof HarbormasterBuildableInterface) {
|
||||
$types[] = PhabricatorTransactions::TYPE_BUILDABLE;
|
||||
}
|
||||
|
||||
if ($this->object instanceof PhabricatorTokenReceiverInterface) {
|
||||
$types[] = PhabricatorTransactions::TYPE_TOKEN;
|
||||
}
|
||||
|
@ -469,7 +465,6 @@ abstract class PhabricatorApplicationTransactionEditor
|
|||
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
||||
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
||||
case PhabricatorTransactions::TYPE_JOIN_POLICY:
|
||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||
case PhabricatorTransactions::TYPE_TOKEN:
|
||||
case PhabricatorTransactions::TYPE_INLINESTATE:
|
||||
case PhabricatorTransactions::TYPE_SUBTYPE:
|
||||
|
@ -610,7 +605,6 @@ abstract class PhabricatorApplicationTransactionEditor
|
|||
return $field->applyApplicationTransactionInternalEffects($xaction);
|
||||
case PhabricatorTransactions::TYPE_CREATE:
|
||||
case PhabricatorTransactions::TYPE_SUBTYPE:
|
||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||
case PhabricatorTransactions::TYPE_TOKEN:
|
||||
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
||||
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
||||
|
@ -673,7 +667,6 @@ abstract class PhabricatorApplicationTransactionEditor
|
|||
case PhabricatorTransactions::TYPE_CREATE:
|
||||
case PhabricatorTransactions::TYPE_SUBTYPE:
|
||||
case PhabricatorTransactions::TYPE_EDGE:
|
||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||
case PhabricatorTransactions::TYPE_TOKEN:
|
||||
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
||||
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
||||
|
|
|
@ -54,7 +54,6 @@ abstract class PhabricatorApplicationTransaction
|
|||
|
||||
public function shouldGenerateOldValue() {
|
||||
switch ($this->getTransactionType()) {
|
||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||
case PhabricatorTransactions::TYPE_TOKEN:
|
||||
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
||||
case PhabricatorTransactions::TYPE_INLINESTATE:
|
||||
|
@ -339,12 +338,6 @@ abstract class PhabricatorApplicationTransaction
|
|||
break;
|
||||
case PhabricatorTransactions::TYPE_TOKEN:
|
||||
break;
|
||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||
$phid = $this->getMetadataValue('harbormaster:buildablePHID');
|
||||
if ($phid) {
|
||||
$phids[] = array($phid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->getComment()) {
|
||||
|
@ -470,8 +463,6 @@ abstract class PhabricatorApplicationTransaction
|
|||
return 'fa-ambulance';
|
||||
}
|
||||
return 'fa-link';
|
||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||
return 'fa-wrench';
|
||||
case PhabricatorTransactions::TYPE_TOKEN:
|
||||
return 'fa-trophy';
|
||||
case PhabricatorTransactions::TYPE_SPACE:
|
||||
|
@ -515,14 +506,6 @@ abstract class PhabricatorApplicationTransaction
|
|||
return 'sky';
|
||||
}
|
||||
break;
|
||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||
switch ($this->getNewValue()) {
|
||||
case HarbormasterBuildableStatus::STATUS_PASSED:
|
||||
return 'green';
|
||||
case HarbormasterBuildableStatus::STATUS_FAILED:
|
||||
return 'red';
|
||||
}
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -679,15 +662,6 @@ abstract class PhabricatorApplicationTransaction
|
|||
switch ($this->getTransactionType()) {
|
||||
case PhabricatorTransactions::TYPE_TOKEN:
|
||||
return true;
|
||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||
switch ($this->getNewValue()) {
|
||||
case HarbormasterBuildableStatus::STATUS_FAILED:
|
||||
// For now, only ever send mail when builds fail. We might let
|
||||
// you customize this later, but in most cases this is probably
|
||||
// completely uninteresting.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case PhabricatorTransactions::TYPE_EDGE:
|
||||
$edge_type = $this->getMetadataValue('edge:type');
|
||||
switch ($edge_type) {
|
||||
|
@ -742,16 +716,6 @@ abstract class PhabricatorApplicationTransaction
|
|||
switch ($this->getTransactionType()) {
|
||||
case PhabricatorTransactions::TYPE_TOKEN:
|
||||
return true;
|
||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||
switch ($this->getNewValue()) {
|
||||
case HarbormasterBuildableStatus::STATUS_FAILED:
|
||||
// For now, don't notify on build passes either. These are pretty
|
||||
// high volume and annoying, with very little present value. We
|
||||
// might want to turn them back on in the specific case of
|
||||
// build successes on the current document?
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case PhabricatorTransactions::TYPE_EDGE:
|
||||
$edge_type = $this->getMetadataValue('edge:type');
|
||||
switch ($edge_type) {
|
||||
|
@ -1027,30 +991,6 @@ abstract class PhabricatorApplicationTransaction
|
|||
$this->renderHandleLink($author_phid));
|
||||
}
|
||||
|
||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||
switch ($this->getNewValue()) {
|
||||
case HarbormasterBuildableStatus::STATUS_BUILDING:
|
||||
return pht(
|
||||
'%s started building %s.',
|
||||
$this->renderHandleLink($author_phid),
|
||||
$this->renderHandleLink(
|
||||
$this->getMetadataValue('harbormaster:buildablePHID')));
|
||||
case HarbormasterBuildableStatus::STATUS_PASSED:
|
||||
return pht(
|
||||
'%s completed building %s.',
|
||||
$this->renderHandleLink($author_phid),
|
||||
$this->renderHandleLink(
|
||||
$this->getMetadataValue('harbormaster:buildablePHID')));
|
||||
case HarbormasterBuildableStatus::STATUS_FAILED:
|
||||
return pht(
|
||||
'%s failed to build %s!',
|
||||
$this->renderHandleLink($author_phid),
|
||||
$this->renderHandleLink(
|
||||
$this->getMetadataValue('harbormaster:buildablePHID')));
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
case PhabricatorTransactions::TYPE_INLINESTATE:
|
||||
$done = 0;
|
||||
$undone = 0;
|
||||
|
@ -1239,32 +1179,6 @@ abstract class PhabricatorApplicationTransaction
|
|||
$this->renderHandleLink($author_phid),
|
||||
$this->renderHandleLink($object_phid));
|
||||
}
|
||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||
switch ($this->getNewValue()) {
|
||||
case HarbormasterBuildableStatus::STATUS_BUILDING:
|
||||
return pht(
|
||||
'%s started building %s for %s.',
|
||||
$this->renderHandleLink($author_phid),
|
||||
$this->renderHandleLink(
|
||||
$this->getMetadataValue('harbormaster:buildablePHID')),
|
||||
$this->renderHandleLink($object_phid));
|
||||
case HarbormasterBuildableStatus::STATUS_PASSED:
|
||||
return pht(
|
||||
'%s completed building %s for %s.',
|
||||
$this->renderHandleLink($author_phid),
|
||||
$this->renderHandleLink(
|
||||
$this->getMetadataValue('harbormaster:buildablePHID')),
|
||||
$this->renderHandleLink($object_phid));
|
||||
case HarbormasterBuildableStatus::STATUS_FAILED:
|
||||
return pht(
|
||||
'%s failed to build %s for %s.',
|
||||
$this->renderHandleLink($author_phid),
|
||||
$this->renderHandleLink(
|
||||
$this->getMetadataValue('harbormaster:buildablePHID')),
|
||||
$this->renderHandleLink($object_phid));
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
case PhabricatorTransactions::TYPE_COLUMNS:
|
||||
$moves = $this->getInterestingMoves($new);
|
||||
|
@ -1421,15 +1335,6 @@ abstract class PhabricatorApplicationTransaction
|
|||
return pht('Changed Policy');
|
||||
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
||||
return pht('Changed Subscribers');
|
||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||
switch ($this->getNewValue()) {
|
||||
case HarbormasterBuildableStatus::STATUS_PASSED:
|
||||
return pht('Build Passed');
|
||||
case HarbormasterBuildableStatus::STATUS_FAILED:
|
||||
return pht('Build Failed');
|
||||
default:
|
||||
return pht('Build Status');
|
||||
}
|
||||
default:
|
||||
return pht('Updated');
|
||||
}
|
||||
|
|
|
@ -100,6 +100,14 @@ abstract class PhabricatorModularTransaction
|
|||
return parent::shouldHideForFeed();
|
||||
}
|
||||
|
||||
/* final */ public function shouldHideForMail(array $xactions) {
|
||||
if ($this->getTransactionImplementation()->shouldHideForMail()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return parent::shouldHideForMail($xactions);
|
||||
}
|
||||
|
||||
/* final */ public function getIcon() {
|
||||
$icon = $this->getTransactionImplementation()->getIcon();
|
||||
if ($icon !== null) {
|
||||
|
@ -168,7 +176,7 @@ abstract class PhabricatorModularTransaction
|
|||
return parent::attachViewer($viewer);
|
||||
}
|
||||
|
||||
/* final */ public function hasChangeDetails() {
|
||||
final public function hasChangeDetails() {
|
||||
if ($this->getTransactionImplementation()->hasChangeDetailView()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -176,7 +184,7 @@ abstract class PhabricatorModularTransaction
|
|||
return parent::hasChangeDetails();
|
||||
}
|
||||
|
||||
/* final */ public function renderChangeDetails(PhabricatorUser $viewer) {
|
||||
final public function renderChangeDetails(PhabricatorUser $viewer) {
|
||||
$impl = $this->getTransactionImplementation();
|
||||
$impl->setViewer($viewer);
|
||||
$view = $impl->newChangeDetailView();
|
||||
|
|
|
@ -51,6 +51,10 @@ abstract class PhabricatorModularTransactionType
|
|||
return false;
|
||||
}
|
||||
|
||||
public function shouldHideForMail() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getIcon() {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -74,9 +74,6 @@ often well-correlated with complexity.
|
|||
We generally follow these practices in Phabricator. The median change size for
|
||||
Phabricator is 35 lines.
|
||||
|
||||
See @{article:Differential User Guide: Large Changes} for information about
|
||||
reviewing big checkins.
|
||||
|
||||
= Write Sensible Commit Messages =
|
||||
|
||||
There are lots of resources for this on the internet. All of them say pretty
|
||||
|
|
|
@ -66,8 +66,6 @@ Continue by:
|
|||
- diving into the details of inline comments in
|
||||
@{article:Differential User Guide: Inline Comments}; or
|
||||
- reading the FAQ at @{article:Differential User Guide: FAQ}; or
|
||||
- learning about handling large changesets in
|
||||
@{article:Differential User Guide: Large Changes}; or
|
||||
- learning about test plans in
|
||||
@{article:Differential User Guide: Test Plans}; or
|
||||
- learning more about Herald in @{article:Herald User Guide}.
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
@title Differential User Guide: Large Changes
|
||||
@group userguide
|
||||
|
||||
Dealing with huge changesets, and when **not** to use Differential.
|
||||
|
||||
= Overview =
|
||||
|
||||
When you want code review for a given changeset, Differential is not always the
|
||||
right tool to use. The rule of thumb is that you should only send changes to
|
||||
Differential if you expect humans to review the actual differences in the source
|
||||
code from the web interface. This should cover the vast majority of changes but,
|
||||
for example, you usually should //not// submit changes like these through
|
||||
Differential:
|
||||
|
||||
- Committing an entire open source project to a private repo somewhere so
|
||||
you can fork it or link against it.
|
||||
- Committing an enormous text datafile, like a list of every English word or a
|
||||
dump of a database.
|
||||
- Making a trivial (e.g., find/replace or codemod) edit to 10,000 files.
|
||||
|
||||
You can still try submitting these kinds of changes, but you may encounter
|
||||
problems getting them to work (database or connection timeouts, for example).
|
||||
Differential is pretty fast and scalable, but at some point either it or the
|
||||
browser will break down: you simply can't show nine million files on a webpage.
|
||||
|
||||
More importantly, in all these cases, the text of the changes won't be reviewed
|
||||
by a human. The metadata associated with the change is what needs review (e.g.,
|
||||
what are you checking in, where are you putting it, and why? Does the change
|
||||
make sense? In the case of automated transformations, what script did you use?).
|
||||
To get review for these types of changes, one of these strategies will usually
|
||||
work better than trying to get the entire change into Differential:
|
||||
|
||||
- Send an email/AIM/IRC to your reviewer(s) like "Hey, I'm going to check in
|
||||
the source for MySQL 9.3.1 to /full/path/to/whatever. The change is staged
|
||||
in /home/whatever/path/somewhere if you want to take a look. Can I put your
|
||||
name on the review?". This is best for straightforward changes. The reviewer
|
||||
is not going to review MySQL's source itself, instead they are reviewing the
|
||||
change metadata: which version are you checking in, why are you checking it
|
||||
in, and where are you putting it? You won't be able to use "arc commit" or
|
||||
"arc amend" to actually push the change. Just use "svn" or "git" and
|
||||
manually edit the commit message instead. (It is normally sufficient to add
|
||||
a "Reviewed By: <username>" field.)
|
||||
- Create a Differential revision with only the metadata, like the script you
|
||||
used to make automated changes or a text file explaining what you're doing,
|
||||
and maybe a sample of some of the changes if they were automated. Include a
|
||||
link to where the changes are staged so reviewers can look at the actual
|
||||
changeset if they want to. This is best for more complicated changes, since
|
||||
Differential can still be used for discussion and provide a permanent record
|
||||
others can refer to. Once the revision is accepted, amend your local commit
|
||||
(e.g. by `git commit --amend`) with the real change and push as usual.
|
||||
|
||||
These kinds of changes are generally rare and don't have much in common, which
|
||||
is why there's no explicit support for them in Differential. If you frequently
|
||||
run into cases which Differential doesn't handle, let us know what they are.
|
|
@ -52,4 +52,9 @@ final class PhabricatorYoutubeRemarkupRule extends PhutilRemarkupRule {
|
|||
return $this->getEngine()->storeText($iframe);
|
||||
}
|
||||
|
||||
public function didMarkupText() {
|
||||
CelerityAPI::getStaticResourceResponse()
|
||||
->addContentSecurityPolicyURI('frame-src', 'https://www.youtube.com/');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -687,3 +687,32 @@ ul.phui-oi-list-view .phui-oi-selectable
|
|||
.phui-oi-frame {
|
||||
border-color: {$blueborder};
|
||||
}
|
||||
|
||||
.differential-revision-size {
|
||||
padding: 0 4px;
|
||||
border-radius: 4px;
|
||||
background: {$lightgreybackground};
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.differential-revision-size .phui-icon-view {
|
||||
margin: 0 1px 0 1px;
|
||||
font-size: smaller;
|
||||
color: {$blueborder};
|
||||
}
|
||||
|
||||
.differential-revision-large {
|
||||
background: {$sh-redbackground};
|
||||
}
|
||||
|
||||
.differential-revision-large .phui-icon-view {
|
||||
color: {$red};
|
||||
}
|
||||
|
||||
.differential-revision-small {
|
||||
background: {$sh-greenbackground};
|
||||
}
|
||||
|
||||
.differential-revision-small .phui-icon-view {
|
||||
color: {$green};
|
||||
}
|
||||
|
|
|
@ -49,6 +49,10 @@ img.phui-image-disabled {
|
|||
color: {$bluetext};
|
||||
}
|
||||
|
||||
.phui-icon-view.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* - Icon in a Circle ------------------------------------------------------- */
|
||||
|
||||
.phui-icon-circle {
|
||||
|
|
Loading…
Add table
Reference in a new issue