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

(stable) Promote 2017 Week 2

This commit is contained in:
epriestley 2017-01-13 14:39:57 -08:00
commit 0426ce73f0
153 changed files with 3502 additions and 1149 deletions

View file

@ -12,8 +12,8 @@ return array(
'core.pkg.css' => '9c725fa0',
'core.pkg.js' => 'a2ead3fe',
'darkconsole.pkg.js' => 'e7393ebb',
'differential.pkg.css' => 'f69afb45',
'differential.pkg.js' => '40b18f35',
'differential.pkg.css' => '9535a7e6',
'differential.pkg.js' => 'ddfeb49b',
'diffusion.pkg.css' => '91c5d3a6',
'diffusion.pkg.js' => '84c8f8fd',
'favicon.ico' => '30672e08',
@ -59,7 +59,7 @@ return array(
'rsrc/css/application/dashboard/dashboard.css' => 'bc6f2127',
'rsrc/css/application/diff/inline-comment-summary.css' => '51efda3a',
'rsrc/css/application/differential/add-comment.css' => 'c47f8c40',
'rsrc/css/application/differential/changeset-view.css' => '11395d9c',
'rsrc/css/application/differential/changeset-view.css' => 'e1621fd5',
'rsrc/css/application/differential/core.css' => '5b7b8ff4',
'rsrc/css/application/differential/phui-inline-comment.css' => '5953c28e',
'rsrc/css/application/differential/revision-comment.css' => '14b8565a',
@ -399,13 +399,12 @@ return array(
'rsrc/js/application/diff/behavior-preview-link.js' => '051c7832',
'rsrc/js/application/differential/ChangesetViewManager.js' => 'a2828756',
'rsrc/js/application/differential/DifferentialInlineCommentEditor.js' => '2e3f9738',
'rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js' => 'e10f8e18',
'rsrc/js/application/differential/behavior-comment-jump.js' => '4fdb476d',
'rsrc/js/application/differential/behavior-comment-preview.js' => 'b064af76',
'rsrc/js/application/differential/behavior-diff-radios.js' => 'e1ff79b1',
'rsrc/js/application/differential/behavior-dropdown-menus.js' => '9a6b9324',
'rsrc/js/application/differential/behavior-edit-inline-comments.js' => '4fbbc3e9',
'rsrc/js/application/differential/behavior-keyboard-nav.js' => '2c426492',
'rsrc/js/application/differential/behavior-keyboard-nav.js' => '92904457',
'rsrc/js/application/differential/behavior-populate.js' => '8694b1df',
'rsrc/js/application/differential/behavior-toggle-files.js' => 'ca3f91eb',
'rsrc/js/application/differential/behavior-user-select.js' => 'a8d8459d',
@ -574,7 +573,7 @@ return array(
'conpherence-thread-manager' => 'c8b5ee6f',
'conpherence-transaction-css' => '85129c68',
'd3' => 'a11a5ff2',
'differential-changeset-view-css' => '11395d9c',
'differential-changeset-view-css' => 'e1621fd5',
'differential-core-view-css' => '5b7b8ff4',
'differential-inline-comment-editor' => '2e3f9738',
'differential-revision-add-comment-css' => 'c47f8c40',
@ -627,13 +626,12 @@ return array(
'javelin-behavior-detect-timezone' => '4c193c96',
'javelin-behavior-device' => 'bb1dd507',
'javelin-behavior-diff-preview-link' => '051c7832',
'javelin-behavior-differential-add-reviewers-and-ccs' => 'e10f8e18',
'javelin-behavior-differential-comment-jump' => '4fdb476d',
'javelin-behavior-differential-diff-radios' => 'e1ff79b1',
'javelin-behavior-differential-dropdown-menus' => '9a6b9324',
'javelin-behavior-differential-edit-inline-comments' => '4fbbc3e9',
'javelin-behavior-differential-feedback-preview' => 'b064af76',
'javelin-behavior-differential-keyboard-navigation' => '2c426492',
'javelin-behavior-differential-keyboard-navigation' => '92904457',
'javelin-behavior-differential-populate' => '8694b1df',
'javelin-behavior-differential-toggle-files' => 'ca3f91eb',
'javelin-behavior-differential-user-select' => 'a8d8459d',
@ -1032,9 +1030,6 @@ return array(
'javelin-dom',
'javelin-typeahead-normalizer',
),
'11395d9c' => array(
'phui-inline-comment-view-css',
),
'12884df9' => array(
'javelin-behavior',
'javelin-stratcom',
@ -1147,12 +1142,6 @@ return array(
'javelin-install',
'javelin-util',
),
'2c426492' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'phabricator-keyboard-shortcut',
),
'2caa8fb8' => array(
'javelin-install',
'javelin-event',
@ -1654,6 +1643,12 @@ return array(
'javelin-dom',
'javelin-request',
),
92904457 => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'phabricator-keyboard-shortcut',
),
'92b9ec77' => array(
'javelin-behavior',
'javelin-stratcom',
@ -2089,10 +2084,8 @@ return array(
'javelin-request',
'javelin-util',
),
'e10f8e18' => array(
'javelin-behavior',
'javelin-dom',
'phabricator-prefab',
'e1621fd5' => array(
'phui-inline-comment-view-css',
),
'e1d25dfb' => array(
'javelin-behavior',
@ -2463,7 +2456,6 @@ return array(
'javelin-behavior-differential-populate',
'javelin-behavior-differential-diff-radios',
'javelin-behavior-differential-comment-jump',
'javelin-behavior-differential-add-reviewers-and-ccs',
'javelin-behavior-differential-keyboard-navigation',
'javelin-behavior-aphront-drag-and-drop-textarea',
'javelin-behavior-phabricator-object-selector',

View file

@ -195,7 +195,6 @@ return array(
'javelin-behavior-differential-populate',
'javelin-behavior-differential-diff-radios',
'javelin-behavior-differential-comment-jump',
'javelin-behavior-differential-add-reviewers-and-ccs',
'javelin-behavior-differential-keyboard-navigation',
'javelin-behavior-aphront-drag-and-drop-textarea',
'javelin-behavior-phabricator-object-selector',

View file

@ -28,7 +28,8 @@ foreach (new LiskRawMigrationIterator($conn, $src_table) as $row) {
DifferentialModernHunk::DATATYPE_TEXT,
'utf8',
DifferentialModernHunk::DATAFORMAT_RAW,
$row['changes'],
// In rare cases, this could be NULL. See T12090.
(string)$row['changes'],
$row['dateCreated'],
$row['dateModified']);
}

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_search.search_profilepanelconfiguration
ADD customPHID VARBINARY(64);

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_differential.differential_diff
ADD commitPHID VARBINARY(64);

View file

@ -5,7 +5,11 @@
// script, except it loads the Phabricator environment and adds some Phabricator
// specific flags.
declare(ticks = 1);
if (function_exists('pcntl_async_signals')) {
pcntl_async_signals(true);
} else {
declare(ticks = 1);
}
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';

View file

@ -7,7 +7,11 @@
// In some cases, Subversion sends us SIGTERM. If we don't catch the signal and
// react to it, we won't run object destructors by default and thus won't clean
// up temporary files. Declare ticks so we can install a signal handler.
declare(ticks=1);
if (function_exists('pcntl_async_signals')) {
pcntl_async_signals(true);
} else {
declare(ticks = 1);
}
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';

View file

@ -519,6 +519,7 @@ phutil_register_library_map(array(
'DifferentialRevisionControlSystem' => 'applications/differential/constants/DifferentialRevisionControlSystem.php',
'DifferentialRevisionDependedOnByRevisionEdgeType' => 'applications/differential/edge/DifferentialRevisionDependedOnByRevisionEdgeType.php',
'DifferentialRevisionDependsOnRevisionEdgeType' => 'applications/differential/edge/DifferentialRevisionDependsOnRevisionEdgeType.php',
'DifferentialRevisionDraftEngine' => 'applications/differential/engine/DifferentialRevisionDraftEngine.php',
'DifferentialRevisionEditConduitAPIMethod' => 'applications/differential/conduit/DifferentialRevisionEditConduitAPIMethod.php',
'DifferentialRevisionEditController' => 'applications/differential/controller/DifferentialRevisionEditController.php',
'DifferentialRevisionEditEngine' => 'applications/differential/editor/DifferentialRevisionEditEngine.php',
@ -612,18 +613,25 @@ phutil_register_library_map(array(
'DiffusionCloneURIView' => 'applications/diffusion/view/DiffusionCloneURIView.php',
'DiffusionCommandEngine' => 'applications/diffusion/protocol/DiffusionCommandEngine.php',
'DiffusionCommandEngineTestCase' => 'applications/diffusion/protocol/__tests__/DiffusionCommandEngineTestCase.php',
'DiffusionCommitAcceptTransaction' => 'applications/diffusion/xaction/DiffusionCommitAcceptTransaction.php',
'DiffusionCommitActionTransaction' => 'applications/diffusion/xaction/DiffusionCommitActionTransaction.php',
'DiffusionCommitAffectedFilesHeraldField' => 'applications/diffusion/herald/DiffusionCommitAffectedFilesHeraldField.php',
'DiffusionCommitAuditTransaction' => 'applications/diffusion/xaction/DiffusionCommitAuditTransaction.php',
'DiffusionCommitAuditorsTransaction' => 'applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php',
'DiffusionCommitAuthorHeraldField' => 'applications/diffusion/herald/DiffusionCommitAuthorHeraldField.php',
'DiffusionCommitAutocloseHeraldField' => 'applications/diffusion/herald/DiffusionCommitAutocloseHeraldField.php',
'DiffusionCommitBranchesController' => 'applications/diffusion/controller/DiffusionCommitBranchesController.php',
'DiffusionCommitBranchesHeraldField' => 'applications/diffusion/herald/DiffusionCommitBranchesHeraldField.php',
'DiffusionCommitCommitterHeraldField' => 'applications/diffusion/herald/DiffusionCommitCommitterHeraldField.php',
'DiffusionCommitConcernTransaction' => 'applications/diffusion/xaction/DiffusionCommitConcernTransaction.php',
'DiffusionCommitController' => 'applications/diffusion/controller/DiffusionCommitController.php',
'DiffusionCommitDiffContentAddedHeraldField' => 'applications/diffusion/herald/DiffusionCommitDiffContentAddedHeraldField.php',
'DiffusionCommitDiffContentHeraldField' => 'applications/diffusion/herald/DiffusionCommitDiffContentHeraldField.php',
'DiffusionCommitDiffContentRemovedHeraldField' => 'applications/diffusion/herald/DiffusionCommitDiffContentRemovedHeraldField.php',
'DiffusionCommitDiffEnormousHeraldField' => 'applications/diffusion/herald/DiffusionCommitDiffEnormousHeraldField.php',
'DiffusionCommitEditConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionCommitEditConduitAPIMethod.php',
'DiffusionCommitEditController' => 'applications/diffusion/controller/DiffusionCommitEditController.php',
'DiffusionCommitEditEngine' => 'applications/diffusion/editor/DiffusionCommitEditEngine.php',
'DiffusionCommitFulltextEngine' => 'applications/repository/search/DiffusionCommitFulltextEngine.php',
'DiffusionCommitHasRevisionEdgeType' => 'applications/diffusion/edge/DiffusionCommitHasRevisionEdgeType.php',
'DiffusionCommitHasRevisionRelationship' => 'applications/diffusion/relationships/DiffusionCommitHasRevisionRelationship.php',
@ -635,6 +643,7 @@ phutil_register_library_map(array(
'DiffusionCommitHintQuery' => 'applications/diffusion/query/DiffusionCommitHintQuery.php',
'DiffusionCommitHookEngine' => 'applications/diffusion/engine/DiffusionCommitHookEngine.php',
'DiffusionCommitHookRejectException' => 'applications/diffusion/exception/DiffusionCommitHookRejectException.php',
'DiffusionCommitListController' => 'applications/diffusion/controller/DiffusionCommitListController.php',
'DiffusionCommitMergeHeraldField' => 'applications/diffusion/herald/DiffusionCommitMergeHeraldField.php',
'DiffusionCommitMessageHeraldField' => 'applications/diffusion/herald/DiffusionCommitMessageHeraldField.php',
'DiffusionCommitPackageAuditHeraldField' => 'applications/diffusion/herald/DiffusionCommitPackageAuditHeraldField.php',
@ -649,6 +658,9 @@ phutil_register_library_map(array(
'DiffusionCommitRemarkupRuleTestCase' => 'applications/diffusion/remarkup/__tests__/DiffusionCommitRemarkupRuleTestCase.php',
'DiffusionCommitRepositoryHeraldField' => 'applications/diffusion/herald/DiffusionCommitRepositoryHeraldField.php',
'DiffusionCommitRepositoryProjectsHeraldField' => 'applications/diffusion/herald/DiffusionCommitRepositoryProjectsHeraldField.php',
'DiffusionCommitRequiredActionResultBucket' => 'applications/diffusion/query/DiffusionCommitRequiredActionResultBucket.php',
'DiffusionCommitResignTransaction' => 'applications/diffusion/xaction/DiffusionCommitResignTransaction.php',
'DiffusionCommitResultBucket' => 'applications/diffusion/query/DiffusionCommitResultBucket.php',
'DiffusionCommitRevertedByCommitEdgeType' => 'applications/diffusion/edge/DiffusionCommitRevertedByCommitEdgeType.php',
'DiffusionCommitRevertsCommitEdgeType' => 'applications/diffusion/edge/DiffusionCommitRevertsCommitEdgeType.php',
'DiffusionCommitReviewerHeraldField' => 'applications/diffusion/herald/DiffusionCommitReviewerHeraldField.php',
@ -656,7 +668,9 @@ phutil_register_library_map(array(
'DiffusionCommitRevisionHeraldField' => 'applications/diffusion/herald/DiffusionCommitRevisionHeraldField.php',
'DiffusionCommitRevisionReviewersHeraldField' => 'applications/diffusion/herald/DiffusionCommitRevisionReviewersHeraldField.php',
'DiffusionCommitRevisionSubscribersHeraldField' => 'applications/diffusion/herald/DiffusionCommitRevisionSubscribersHeraldField.php',
'DiffusionCommitSearchConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionCommitSearchConduitAPIMethod.php',
'DiffusionCommitTagsController' => 'applications/diffusion/controller/DiffusionCommitTagsController.php',
'DiffusionCommitTransactionType' => 'applications/diffusion/xaction/DiffusionCommitTransactionType.php',
'DiffusionCompareController' => 'applications/diffusion/controller/DiffusionCompareController.php',
'DiffusionConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionConduitAPIMethod.php',
'DiffusionController' => 'applications/diffusion/controller/DiffusionController.php',
@ -1858,19 +1872,16 @@ phutil_register_library_map(array(
'PhabricatorAsanaSubtaskHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorAsanaSubtaskHasObjectEdgeType.php',
'PhabricatorAsanaTaskHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorAsanaTaskHasObjectEdgeType.php',
'PhabricatorAuditActionConstants' => 'applications/audit/constants/PhabricatorAuditActionConstants.php',
'PhabricatorAuditAddCommentController' => 'applications/audit/controller/PhabricatorAuditAddCommentController.php',
'PhabricatorAuditApplication' => 'applications/audit/application/PhabricatorAuditApplication.php',
'PhabricatorAuditCommentEditor' => 'applications/audit/editor/PhabricatorAuditCommentEditor.php',
'PhabricatorAuditCommitStatusConstants' => 'applications/audit/constants/PhabricatorAuditCommitStatusConstants.php',
'PhabricatorAuditController' => 'applications/audit/controller/PhabricatorAuditController.php',
'PhabricatorAuditEditor' => 'applications/audit/editor/PhabricatorAuditEditor.php',
'PhabricatorAuditInlineComment' => 'applications/audit/storage/PhabricatorAuditInlineComment.php',
'PhabricatorAuditListController' => 'applications/audit/controller/PhabricatorAuditListController.php',
'PhabricatorAuditListView' => 'applications/audit/view/PhabricatorAuditListView.php',
'PhabricatorAuditMailReceiver' => 'applications/audit/mail/PhabricatorAuditMailReceiver.php',
'PhabricatorAuditManagementDeleteWorkflow' => 'applications/audit/management/PhabricatorAuditManagementDeleteWorkflow.php',
'PhabricatorAuditManagementWorkflow' => 'applications/audit/management/PhabricatorAuditManagementWorkflow.php',
'PhabricatorAuditPreviewController' => 'applications/audit/controller/PhabricatorAuditPreviewController.php',
'PhabricatorAuditReplyHandler' => 'applications/audit/mail/PhabricatorAuditReplyHandler.php',
'PhabricatorAuditStatusConstants' => 'applications/audit/constants/PhabricatorAuditStatusConstants.php',
'PhabricatorAuditTransaction' => 'applications/audit/storage/PhabricatorAuditTransaction.php',
@ -2025,6 +2036,7 @@ phutil_register_library_map(array(
'PhabricatorBcryptPasswordHasher' => 'infrastructure/util/password/PhabricatorBcryptPasswordHasher.php',
'PhabricatorBinariesSetupCheck' => 'applications/config/check/PhabricatorBinariesSetupCheck.php',
'PhabricatorBitbucketAuthProvider' => 'applications/auth/provider/PhabricatorBitbucketAuthProvider.php',
'PhabricatorBoardColumnsSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorBoardColumnsSearchEngineAttachment.php',
'PhabricatorBoardLayoutEngine' => 'applications/project/engine/PhabricatorBoardLayoutEngine.php',
'PhabricatorBoardRenderingEngine' => 'applications/project/engine/PhabricatorBoardRenderingEngine.php',
'PhabricatorBoardResponseEngine' => 'applications/project/engine/PhabricatorBoardResponseEngine.php',
@ -2044,6 +2056,7 @@ phutil_register_library_map(array(
'PhabricatorBotUser' => 'infrastructure/daemon/bot/target/PhabricatorBotUser.php',
'PhabricatorBotWhatsNewHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotWhatsNewHandler.php',
'PhabricatorBritishEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorBritishEnglishTranslation.php',
'PhabricatorBuiltinDraftEngine' => 'applications/transactions/draft/PhabricatorBuiltinDraftEngine.php',
'PhabricatorBuiltinPatchList' => 'infrastructure/storage/patch/PhabricatorBuiltinPatchList.php',
'PhabricatorBulkContentSource' => 'infrastructure/daemon/contentsource/PhabricatorBulkContentSource.php',
'PhabricatorBusyUIExample' => 'applications/uiexample/examples/PhabricatorBusyUIExample.php',
@ -2539,6 +2552,8 @@ phutil_register_library_map(array(
'PhabricatorDoorkeeperApplication' => 'applications/doorkeeper/application/PhabricatorDoorkeeperApplication.php',
'PhabricatorDraft' => 'applications/draft/storage/PhabricatorDraft.php',
'PhabricatorDraftDAO' => 'applications/draft/storage/PhabricatorDraftDAO.php',
'PhabricatorDraftEngine' => 'applications/transactions/draft/PhabricatorDraftEngine.php',
'PhabricatorDraftInterface' => 'applications/transactions/draft/PhabricatorDraftInterface.php',
'PhabricatorDrydockApplication' => 'applications/drydock/application/PhabricatorDrydockApplication.php',
'PhabricatorEdgeConfig' => 'infrastructure/edges/constants/PhabricatorEdgeConfig.php',
'PhabricatorEdgeConstants' => 'infrastructure/edges/constants/PhabricatorEdgeConstants.php',
@ -2653,6 +2668,13 @@ phutil_register_library_map(array(
'PhabricatorFactSimpleSpec' => 'applications/fact/spec/PhabricatorFactSimpleSpec.php',
'PhabricatorFactSpec' => 'applications/fact/spec/PhabricatorFactSpec.php',
'PhabricatorFactUpdateIterator' => 'applications/fact/extract/PhabricatorFactUpdateIterator.php',
'PhabricatorFavoritesApplication' => 'applications/favorites/application/PhabricatorFavoritesApplication.php',
'PhabricatorFavoritesConstants' => 'applications/favorites/constants/PhabricatorFavoritesConstants.php',
'PhabricatorFavoritesController' => 'applications/favorites/controller/PhabricatorFavoritesController.php',
'PhabricatorFavoritesMainController' => 'applications/favorites/controller/PhabricatorFavoritesMainController.php',
'PhabricatorFavoritesManageProfileMenuItem' => 'applications/favorites/menuitem/PhabricatorFavoritesManageProfileMenuItem.php',
'PhabricatorFavoritesMenuItemController' => 'applications/favorites/controller/PhabricatorFavoritesMenuItemController.php',
'PhabricatorFavoritesProfileMenuEngine' => 'applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php',
'PhabricatorFaxContentSource' => 'infrastructure/contentsource/PhabricatorFaxContentSource.php',
'PhabricatorFeedApplication' => 'applications/feed/application/PhabricatorFeedApplication.php',
'PhabricatorFeedBuilder' => 'applications/feed/builder/PhabricatorFeedBuilder.php',
@ -2810,9 +2832,14 @@ phutil_register_library_map(array(
'PhabricatorHeraldContentSource' => 'applications/herald/contentsource/PhabricatorHeraldContentSource.php',
'PhabricatorHighSecurityRequestExceptionHandler' => 'aphront/handler/PhabricatorHighSecurityRequestExceptionHandler.php',
'PhabricatorHomeApplication' => 'applications/home/application/PhabricatorHomeApplication.php',
'PhabricatorHomeConstants' => 'applications/home/constants/PhabricatorHomeConstants.php',
'PhabricatorHomeController' => 'applications/home/controller/PhabricatorHomeController.php',
'PhabricatorHomeMainController' => 'applications/home/controller/PhabricatorHomeMainController.php',
'PhabricatorHomeManageProfileMenuItem' => 'applications/home/menuitem/PhabricatorHomeManageProfileMenuItem.php',
'PhabricatorHomeMenuController' => 'applications/home/controller/PhabricatorHomeMenuController.php',
'PhabricatorHomeMenuItemController' => 'applications/home/controller/PhabricatorHomeMenuItemController.php',
'PhabricatorHomePreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorHomePreferencesSettingsPanel.php',
'PhabricatorHomeProfileMenuEngine' => 'applications/home/engine/PhabricatorHomeProfileMenuEngine.php',
'PhabricatorHomeQuickCreateController' => 'applications/home/controller/PhabricatorHomeQuickCreateController.php',
'PhabricatorHovercardEngineExtension' => 'applications/search/engineextension/PhabricatorHovercardEngineExtension.php',
'PhabricatorHovercardEngineExtensionModule' => 'applications/search/engineextension/PhabricatorHovercardEngineExtensionModule.php',
@ -3072,6 +3099,7 @@ phutil_register_library_map(array(
'PhabricatorObjectHasAsanaSubtaskEdgeType' => 'applications/doorkeeper/edge/PhabricatorObjectHasAsanaSubtaskEdgeType.php',
'PhabricatorObjectHasAsanaTaskEdgeType' => 'applications/doorkeeper/edge/PhabricatorObjectHasAsanaTaskEdgeType.php',
'PhabricatorObjectHasContributorEdgeType' => 'applications/transactions/edges/PhabricatorObjectHasContributorEdgeType.php',
'PhabricatorObjectHasDraftEdgeType' => 'applications/transactions/edges/PhabricatorObjectHasDraftEdgeType.php',
'PhabricatorObjectHasFileEdgeType' => 'applications/transactions/edges/PhabricatorObjectHasFileEdgeType.php',
'PhabricatorObjectHasJiraIssueEdgeType' => 'applications/doorkeeper/edge/PhabricatorObjectHasJiraIssueEdgeType.php',
'PhabricatorObjectHasSubscriberEdgeType' => 'applications/transactions/edges/PhabricatorObjectHasSubscriberEdgeType.php',
@ -3426,6 +3454,7 @@ phutil_register_library_map(array(
'PhabricatorProjectColumnPosition' => 'applications/project/storage/PhabricatorProjectColumnPosition.php',
'PhabricatorProjectColumnPositionQuery' => 'applications/project/query/PhabricatorProjectColumnPositionQuery.php',
'PhabricatorProjectColumnQuery' => 'applications/project/query/PhabricatorProjectColumnQuery.php',
'PhabricatorProjectColumnSearchEngine' => 'applications/project/query/PhabricatorProjectColumnSearchEngine.php',
'PhabricatorProjectColumnTransaction' => 'applications/project/storage/PhabricatorProjectColumnTransaction.php',
'PhabricatorProjectColumnTransactionEditor' => 'applications/project/editor/PhabricatorProjectColumnTransactionEditor.php',
'PhabricatorProjectColumnTransactionQuery' => 'applications/project/query/PhabricatorProjectColumnTransactionQuery.php',
@ -3514,6 +3543,7 @@ phutil_register_library_map(array(
'PhabricatorProjectWatcherListView' => 'applications/project/view/PhabricatorProjectWatcherListView.php',
'PhabricatorProjectWorkboardBackgroundColor' => 'applications/project/constants/PhabricatorProjectWorkboardBackgroundColor.php',
'PhabricatorProjectWorkboardProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php',
'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorProjectsAncestorsSearchEngineAttachment.php',
'PhabricatorProjectsCurtainExtension' => 'applications/project/engineextension/PhabricatorProjectsCurtainExtension.php',
'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php',
'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php',
@ -4452,6 +4482,7 @@ phutil_register_library_map(array(
'ProjectAddProjectsEmailCommand' => 'applications/project/command/ProjectAddProjectsEmailCommand.php',
'ProjectBoardTaskCard' => 'applications/project/view/ProjectBoardTaskCard.php',
'ProjectCanLockProjectsCapability' => 'applications/project/capability/ProjectCanLockProjectsCapability.php',
'ProjectColumnSearchConduitAPIMethod' => 'applications/project/conduit/ProjectColumnSearchConduitAPIMethod.php',
'ProjectConduitAPIMethod' => 'applications/project/conduit/ProjectConduitAPIMethod.php',
'ProjectCreateConduitAPIMethod' => 'applications/project/conduit/ProjectCreateConduitAPIMethod.php',
'ProjectCreateProjectsCapability' => 'applications/project/capability/ProjectCreateProjectsCapability.php',
@ -5184,6 +5215,7 @@ phutil_register_library_map(array(
'PhabricatorProjectInterface',
'PhabricatorFulltextInterface',
'PhabricatorConduitResultInterface',
'PhabricatorDraftInterface',
),
'DifferentialRevisionAbandonTransaction' => 'DifferentialRevisionActionTransaction',
'DifferentialRevisionAcceptTransaction' => 'DifferentialRevisionReviewTransaction',
@ -5200,6 +5232,7 @@ phutil_register_library_map(array(
'DifferentialRevisionControlSystem' => 'Phobject',
'DifferentialRevisionDependedOnByRevisionEdgeType' => 'PhabricatorEdgeType',
'DifferentialRevisionDependsOnRevisionEdgeType' => 'PhabricatorEdgeType',
'DifferentialRevisionDraftEngine' => 'PhabricatorDraftEngine',
'DifferentialRevisionEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'DifferentialRevisionEditController' => 'DifferentialController',
'DifferentialRevisionEditEngine' => 'PhabricatorEditEngine',
@ -5293,18 +5326,25 @@ phutil_register_library_map(array(
'DiffusionCloneURIView' => 'AphrontView',
'DiffusionCommandEngine' => 'Phobject',
'DiffusionCommandEngineTestCase' => 'PhabricatorTestCase',
'DiffusionCommitAcceptTransaction' => 'DiffusionCommitAuditTransaction',
'DiffusionCommitActionTransaction' => 'DiffusionCommitTransactionType',
'DiffusionCommitAffectedFilesHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitAuditTransaction' => 'DiffusionCommitActionTransaction',
'DiffusionCommitAuditorsTransaction' => 'DiffusionCommitTransactionType',
'DiffusionCommitAuthorHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitAutocloseHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitBranchesController' => 'DiffusionController',
'DiffusionCommitBranchesHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitCommitterHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitConcernTransaction' => 'DiffusionCommitAuditTransaction',
'DiffusionCommitController' => 'DiffusionController',
'DiffusionCommitDiffContentAddedHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitDiffContentHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitDiffContentRemovedHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitDiffEnormousHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'DiffusionCommitEditController' => 'DiffusionController',
'DiffusionCommitEditEngine' => 'PhabricatorEditEngine',
'DiffusionCommitFulltextEngine' => 'PhabricatorFulltextEngine',
'DiffusionCommitHasRevisionEdgeType' => 'PhabricatorEdgeType',
'DiffusionCommitHasRevisionRelationship' => 'DiffusionCommitRelationship',
@ -5316,6 +5356,7 @@ phutil_register_library_map(array(
'DiffusionCommitHintQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'DiffusionCommitHookEngine' => 'Phobject',
'DiffusionCommitHookRejectException' => 'Exception',
'DiffusionCommitListController' => 'DiffusionController',
'DiffusionCommitMergeHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitMessageHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitPackageAuditHeraldField' => 'DiffusionCommitHeraldField',
@ -5330,6 +5371,9 @@ phutil_register_library_map(array(
'DiffusionCommitRemarkupRuleTestCase' => 'PhabricatorTestCase',
'DiffusionCommitRepositoryHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitRepositoryProjectsHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitRequiredActionResultBucket' => 'DiffusionCommitResultBucket',
'DiffusionCommitResignTransaction' => 'DiffusionCommitAuditTransaction',
'DiffusionCommitResultBucket' => 'PhabricatorSearchResultBucket',
'DiffusionCommitRevertedByCommitEdgeType' => 'PhabricatorEdgeType',
'DiffusionCommitRevertsCommitEdgeType' => 'PhabricatorEdgeType',
'DiffusionCommitReviewerHeraldField' => 'DiffusionCommitHeraldField',
@ -5337,7 +5381,9 @@ phutil_register_library_map(array(
'DiffusionCommitRevisionHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitRevisionReviewersHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitRevisionSubscribersHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'DiffusionCommitTagsController' => 'DiffusionController',
'DiffusionCommitTransactionType' => 'PhabricatorModularTransactionType',
'DiffusionCompareController' => 'DiffusionController',
'DiffusionConduitAPIMethod' => 'ConduitAPIMethod',
'DiffusionController' => 'PhabricatorController',
@ -6723,7 +6769,6 @@ phutil_register_library_map(array(
'PhabricatorAsanaSubtaskHasObjectEdgeType' => 'PhabricatorEdgeType',
'PhabricatorAsanaTaskHasObjectEdgeType' => 'PhabricatorEdgeType',
'PhabricatorAuditActionConstants' => 'Phobject',
'PhabricatorAuditAddCommentController' => 'PhabricatorAuditController',
'PhabricatorAuditApplication' => 'PhabricatorApplication',
'PhabricatorAuditCommentEditor' => 'PhabricatorEditor',
'PhabricatorAuditCommitStatusConstants' => 'Phobject',
@ -6733,15 +6778,13 @@ phutil_register_library_map(array(
'Phobject',
'PhabricatorInlineCommentInterface',
),
'PhabricatorAuditListController' => 'PhabricatorAuditController',
'PhabricatorAuditListView' => 'AphrontView',
'PhabricatorAuditMailReceiver' => 'PhabricatorObjectMailReceiver',
'PhabricatorAuditManagementDeleteWorkflow' => 'PhabricatorAuditManagementWorkflow',
'PhabricatorAuditManagementWorkflow' => 'PhabricatorManagementWorkflow',
'PhabricatorAuditPreviewController' => 'PhabricatorAuditController',
'PhabricatorAuditReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
'PhabricatorAuditStatusConstants' => 'Phobject',
'PhabricatorAuditTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorAuditTransaction' => 'PhabricatorModularTransaction',
'PhabricatorAuditTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PhabricatorAuditTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorAuditTransactionView' => 'PhabricatorApplicationTransactionView',
@ -6925,6 +6968,7 @@ phutil_register_library_map(array(
'PhabricatorBcryptPasswordHasher' => 'PhabricatorPasswordHasher',
'PhabricatorBinariesSetupCheck' => 'PhabricatorSetupCheck',
'PhabricatorBitbucketAuthProvider' => 'PhabricatorOAuth1AuthProvider',
'PhabricatorBoardColumnsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
'PhabricatorBoardLayoutEngine' => 'Phobject',
'PhabricatorBoardRenderingEngine' => 'Phobject',
'PhabricatorBoardResponseEngine' => 'Phobject',
@ -6944,6 +6988,7 @@ phutil_register_library_map(array(
'PhabricatorBotUser' => 'PhabricatorBotTarget',
'PhabricatorBotWhatsNewHandler' => 'PhabricatorBotHandler',
'PhabricatorBritishEnglishTranslation' => 'PhutilTranslation',
'PhabricatorBuiltinDraftEngine' => 'PhabricatorDraftEngine',
'PhabricatorBuiltinPatchList' => 'PhabricatorSQLPatchList',
'PhabricatorBulkContentSource' => 'PhabricatorContentSource',
'PhabricatorBusyUIExample' => 'PhabricatorUIExample',
@ -7522,6 +7567,7 @@ phutil_register_library_map(array(
'PhabricatorDoorkeeperApplication' => 'PhabricatorApplication',
'PhabricatorDraft' => 'PhabricatorDraftDAO',
'PhabricatorDraftDAO' => 'PhabricatorLiskDAO',
'PhabricatorDraftEngine' => 'Phobject',
'PhabricatorDrydockApplication' => 'PhabricatorApplication',
'PhabricatorEdgeConfig' => 'PhabricatorEdgeConstants',
'PhabricatorEdgeConstants' => 'Phobject',
@ -7645,6 +7691,13 @@ phutil_register_library_map(array(
'PhabricatorFactSimpleSpec' => 'PhabricatorFactSpec',
'PhabricatorFactSpec' => 'Phobject',
'PhabricatorFactUpdateIterator' => 'PhutilBufferedIterator',
'PhabricatorFavoritesApplication' => 'PhabricatorApplication',
'PhabricatorFavoritesConstants' => 'PhabricatorFavoritesController',
'PhabricatorFavoritesController' => 'PhabricatorController',
'PhabricatorFavoritesMainController' => 'PhabricatorFavoritesController',
'PhabricatorFavoritesManageProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorFavoritesMenuItemController' => 'PhabricatorFavoritesController',
'PhabricatorFavoritesProfileMenuEngine' => 'PhabricatorProfileMenuEngine',
'PhabricatorFaxContentSource' => 'PhabricatorContentSource',
'PhabricatorFeedApplication' => 'PhabricatorApplication',
'PhabricatorFeedBuilder' => 'Phobject',
@ -7838,9 +7891,14 @@ phutil_register_library_map(array(
'PhabricatorHeraldContentSource' => 'PhabricatorContentSource',
'PhabricatorHighSecurityRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler',
'PhabricatorHomeApplication' => 'PhabricatorApplication',
'PhabricatorHomeConstants' => 'PhabricatorHomeController',
'PhabricatorHomeController' => 'PhabricatorController',
'PhabricatorHomeMainController' => 'PhabricatorHomeController',
'PhabricatorHomeManageProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorHomeMenuController' => 'PhabricatorHomeController',
'PhabricatorHomeMenuItemController' => 'PhabricatorHomeController',
'PhabricatorHomePreferencesSettingsPanel' => 'PhabricatorSettingsPanel',
'PhabricatorHomeProfileMenuEngine' => 'PhabricatorProfileMenuEngine',
'PhabricatorHomeQuickCreateController' => 'PhabricatorHomeController',
'PhabricatorHovercardEngineExtension' => 'Phobject',
'PhabricatorHovercardEngineExtensionModule' => 'PhabricatorConfigModule',
@ -8123,6 +8181,7 @@ phutil_register_library_map(array(
'PhabricatorObjectHasAsanaSubtaskEdgeType' => 'PhabricatorEdgeType',
'PhabricatorObjectHasAsanaTaskEdgeType' => 'PhabricatorEdgeType',
'PhabricatorObjectHasContributorEdgeType' => 'PhabricatorEdgeType',
'PhabricatorObjectHasDraftEdgeType' => 'PhabricatorEdgeType',
'PhabricatorObjectHasFileEdgeType' => 'PhabricatorEdgeType',
'PhabricatorObjectHasJiraIssueEdgeType' => 'PhabricatorEdgeType',
'PhabricatorObjectHasSubscriberEdgeType' => 'PhabricatorEdgeType',
@ -8562,6 +8621,7 @@ phutil_register_library_map(array(
'PhabricatorPolicyInterface',
'PhabricatorDestructibleInterface',
'PhabricatorExtendedPolicyInterface',
'PhabricatorConduitResultInterface',
),
'PhabricatorProjectColumnDetailController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectColumnEditController' => 'PhabricatorProjectBoardController',
@ -8573,6 +8633,7 @@ phutil_register_library_map(array(
),
'PhabricatorProjectColumnPositionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorProjectColumnQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorProjectColumnSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorProjectColumnTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorProjectColumnTransactionEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorProjectColumnTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
@ -8666,6 +8727,7 @@ phutil_register_library_map(array(
'PhabricatorProjectWatcherListView' => 'PhabricatorProjectUserListView',
'PhabricatorProjectWorkboardBackgroundColor' => 'Phobject',
'PhabricatorProjectWorkboardProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
'PhabricatorProjectsCurtainExtension' => 'PHUICurtainExtension',
'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension',
'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField',
@ -8733,6 +8795,7 @@ phutil_register_library_map(array(
'PhabricatorCustomFieldInterface',
'PhabricatorApplicationTransactionInterface',
'PhabricatorFulltextInterface',
'PhabricatorConduitResultInterface',
),
'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
@ -9845,6 +9908,7 @@ phutil_register_library_map(array(
'ProjectAddProjectsEmailCommand' => 'MetaMTAEmailTransactionCommand',
'ProjectBoardTaskCard' => 'Phobject',
'ProjectCanLockProjectsCapability' => 'PhabricatorPolicyCapability',
'ProjectColumnSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'ProjectConduitAPIMethod' => 'ConduitAPIMethod',
'ProjectCreateConduitAPIMethod' => 'ProjectConduitAPIMethod',
'ProjectCreateProjectsCapability' => 'PhabricatorPolicyCapability',

View file

@ -3,7 +3,7 @@
final class PhabricatorAuditApplication extends PhabricatorApplication {
public function getBaseURI() {
return '/audit/';
return '/diffusion/commit/';
}
public function getIcon() {
@ -18,84 +18,20 @@ final class PhabricatorAuditApplication extends PhabricatorApplication {
return pht('Browse and Audit Commits');
}
public function canUninstall() {
// Audit was once a separate application, but has largely merged with
// Diffusion.
return false;
}
public function isPinnedByDefault(PhabricatorUser $viewer) {
return true;
}
public function getHelpDocumentationArticles(PhabricatorUser $viewer) {
return array(
array(
'name' => pht('Audit User Guide'),
'href' => PhabricatorEnv::getDoclink('Audit User Guide'),
),
);
}
public function getRoutes() {
return array(
'/audit/' => array(
'(?:query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorAuditListController',
'addcomment/' => 'PhabricatorAuditAddCommentController',
'preview/(?P<id>[1-9]\d*)/' => 'PhabricatorAuditPreviewController',
),
);
return parent::isClassInstalledForViewer(
'PhabricatorDiffusionApplication',
$viewer);
}
public function getApplicationOrder() {
return 0.130;
}
public function loadStatus(PhabricatorUser $user) {
$status = array();
$limit = self::MAX_STATUS_ITEMS;
$phids = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user);
$query = id(new DiffusionCommitQuery())
->setViewer($user)
->withAuthorPHIDs(array($user->getPHID()))
->withAuditStatus(DiffusionCommitQuery::AUDIT_STATUS_CONCERN)
->setLimit($limit);
$commits = $query->execute();
$count = count($commits);
if ($count >= $limit) {
$count_str = pht('%s+ Problem Commits', new PhutilNumber($limit - 1));
} else {
$count_str = pht('%s Problem Commit(s)', new PhutilNumber($count));
}
$type = PhabricatorApplicationStatusView::TYPE_NEEDS_ATTENTION;
$status[] = id(new PhabricatorApplicationStatusView())
->setType($type)
->setText($count_str)
->setCount($count);
$query = id(new DiffusionCommitQuery())
->setViewer($user)
->withNeedsAuditByPHIDs($phids)
->withAuditStatus(DiffusionCommitQuery::AUDIT_STATUS_OPEN)
->setLimit($limit);
$commits = $query->execute();
$count = count($commits);
if ($count >= $limit) {
$count_str = pht(
'%s+ Commits Awaiting Audit',
new PhutilNumber($limit - 1));
} else {
$count_str = pht(
'%s Commit(s) Awaiting Audit',
new PhutilNumber($count));
}
$type = PhabricatorApplicationStatusView::TYPE_WARNING;
$status[] = id(new PhabricatorApplicationStatusView())
->setType($type)
->setText($count_str)
->setCount($count);
return $status;
}
}

View file

@ -3,7 +3,8 @@
abstract class AuditConduitAPIMethod extends ConduitAPIMethod {
final public function getApplication() {
return PhabricatorApplication::getByClass('PhabricatorAuditApplication');
return PhabricatorApplication::getByClass(
'PhabricatorDiffusionApplication');
}
}

View file

@ -2,6 +2,12 @@
final class AuditQueryConduitAPIMethod extends AuditConduitAPIMethod {
const AUDIT_LEGACYSTATUS_ANY = 'audit-status-any';
const AUDIT_LEGACYSTATUS_OPEN = 'audit-status-open';
const AUDIT_LEGACYSTATUS_CONCERN = 'audit-status-concern';
const AUDIT_LEGACYSTATUS_ACCEPTED = 'audit-status-accepted';
const AUDIT_LEGACYSTATUS_PARTIAL = 'audit-status-partial';
public function getAPIMethodName() {
return 'audit.query';
}
@ -10,13 +16,23 @@ final class AuditQueryConduitAPIMethod extends AuditConduitAPIMethod {
return pht('Query audit requests.');
}
public function getMethodStatus() {
return self::METHOD_STATUS_FROZEN;
}
public function getMethodStatusDescription() {
return pht(
'This method is frozen and will eventually be deprecated. New code '.
'should use "diffusion.commit.search" instead.');
}
protected function defineParamTypes() {
$statuses = array(
DiffusionCommitQuery::AUDIT_STATUS_ANY,
DiffusionCommitQuery::AUDIT_STATUS_OPEN,
DiffusionCommitQuery::AUDIT_STATUS_CONCERN,
DiffusionCommitQuery::AUDIT_STATUS_ACCEPTED,
DiffusionCommitQuery::AUDIT_STATUS_PARTIAL,
self::AUDIT_LEGACYSTATUS_ANY,
self::AUDIT_LEGACYSTATUS_OPEN,
self::AUDIT_LEGACYSTATUS_CONCERN,
self::AUDIT_LEGACYSTATUS_ACCEPTED,
self::AUDIT_LEGACYSTATUS_PARTIAL,
);
$status_const = $this->formatStringConstants($statuses);
@ -50,10 +66,26 @@ final class AuditQueryConduitAPIMethod extends AuditConduitAPIMethod {
$query->withPHIDs($commit_phids);
}
$status = $request->getValue(
'status',
DiffusionCommitQuery::AUDIT_STATUS_ANY);
$query->withAuditStatus($status);
$status_map = array(
self::AUDIT_LEGACYSTATUS_OPEN => array(
PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT,
PhabricatorAuditCommitStatusConstants::CONCERN_RAISED,
),
self::AUDIT_LEGACYSTATUS_CONCERN => array(
PhabricatorAuditCommitStatusConstants::CONCERN_RAISED,
),
self::AUDIT_LEGACYSTATUS_ACCEPTED => array(
PhabricatorAuditCommitStatusConstants::CONCERN_ACCEPTED,
),
self::AUDIT_LEGACYSTATUS_PARTIAL => array(
PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED,
),
);
$status = $request->getValue('status');
if (isset($status_map[$status])) {
$query->withStatuses($status_map[$status]);
}
// NOTE: These affect the number of commits identified, which is sort of
// reasonable but means the method may return an arbitrary number of

View file

@ -10,7 +10,7 @@ final class PhabricatorAuditCommitStatusConstants extends Phobject {
public static function getStatusNameMap() {
$map = array(
self::NONE => pht('None'),
self::NONE => pht('No Audits'),
self::NEEDS_AUDIT => pht('Audit Required'),
self::CONCERN_RAISED => pht('Concern Raised'),
self::PARTIALLY_AUDITED => pht('Partially Audited'),
@ -28,6 +28,7 @@ final class PhabricatorAuditCommitStatusConstants extends Phobject {
return array(
self::CONCERN_RAISED,
self::NEEDS_AUDIT,
self::PARTIALLY_AUDITED,
);
}
@ -45,6 +46,9 @@ final class PhabricatorAuditCommitStatusConstants extends Phobject {
case self::FULLY_AUDITED:
$color = 'green';
break;
case self::NONE:
$color = 'bluegrey';
break;
default:
$color = null;
break;
@ -55,13 +59,18 @@ final class PhabricatorAuditCommitStatusConstants extends Phobject {
public static function getStatusIcon($code) {
switch ($code) {
case self::CONCERN_RAISED:
$icon = 'fa-exclamation-circle';
$icon = 'fa-times-circle';
break;
case self::NEEDS_AUDIT:
case self::PARTIALLY_AUDITED:
$icon = 'fa-exclamation-circle';
break;
case self::PARTIALLY_AUDITED:
$icon = 'fa-check-circle-o';
break;
case self::FULLY_AUDITED:
$icon = 'fa-check-circle';
break;
case self::NONE:
$icon = 'fa-check';
break;
default:

View file

@ -28,6 +28,13 @@ final class PhabricatorAuditStatusConstants extends Phobject {
return $map;
}
public static function getActionRequiredStatusConstants() {
return array(
self::AUDIT_REQUIRED,
self::AUDIT_REQUESTED,
);
}
public static function getStatusName($code) {
return idx(self::getStatusNameMap(), $code, pht('Unknown'));
}

View file

@ -1,90 +0,0 @@
<?php
final class PhabricatorAuditAddCommentController
extends PhabricatorAuditController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
if (!$request->isFormPost()) {
return new Aphront403Response();
}
$commit_phid = $request->getStr('commit');
$commit = id(new DiffusionCommitQuery())
->setViewer($viewer)
->withPHIDs(array($commit_phid))
->needAuditRequests(true)
->executeOne();
if (!$commit) {
return new Aphront404Response();
}
$xactions = array();
// make sure we only add auditors or ccs if the action matches
$action = $request->getStr('action');
switch ($action) {
case PhabricatorAuditActionConstants::ADD_AUDITORS:
$auditors = $request->getArr('auditors');
$xactions[] = id(new PhabricatorAuditTransaction())
->setTransactionType(PhabricatorAuditActionConstants::ADD_AUDITORS)
->setNewValue(array_fuse($auditors));
break;
case PhabricatorAuditActionConstants::ADD_CCS:
$xactions[] = id(new PhabricatorAuditTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
->setNewValue(
array(
'+' => $request->getArr('ccs'),
));
break;
case PhabricatorAuditActionConstants::COMMENT:
// We'll deal with this below.
break;
default:
$xactions[] = id(new PhabricatorAuditTransaction())
->setTransactionType(PhabricatorAuditActionConstants::ACTION)
->setNewValue($action);
break;
}
$content = $request->getStr('content');
if (strlen($content)) {
$xactions[] = id(new PhabricatorAuditTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->attachComment(
id(new PhabricatorAuditTransactionComment())
->setCommitPHID($commit->getPHID())
->setContent($content));
}
$inlines = PhabricatorAuditInlineComment::loadDraftComments(
$viewer,
$commit->getPHID());
foreach ($inlines as $inline) {
$xactions[] = id(new PhabricatorAuditTransaction())
->setTransactionType(PhabricatorAuditActionConstants::INLINE)
->attachComment($inline->getTransactionComment());
}
id(new PhabricatorAuditEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnMissingFields(true)
->applyTransactions($commit, $xactions);
$draft = id(new PhabricatorDraft())->loadOneWhere(
'authorPHID = %s AND draftKey = %s',
$viewer->getPHID(),
'diffusion-audit-'.$commit->getID());
if ($draft) {
$draft->delete();
}
$uri = $commit->getURI();
return id(new AphrontRedirectResponse())->setURI($uri);
}
}

View file

@ -1,19 +0,0 @@
<?php
final class PhabricatorAuditListController
extends PhabricatorAuditController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$controller = id(new PhabricatorApplicationSearchController())
->setQueryKey($request->getURIData('queryKey'))
->setSearchEngine(new PhabricatorCommitSearchEngine())
->setNavigation($this->buildSideNavView());
return $this->delegateToController($controller);
}
}

View file

@ -1,82 +0,0 @@
<?php
final class PhabricatorAuditPreviewController
extends PhabricatorAuditController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$commit = id(new PhabricatorRepositoryCommit())->load($id);
if (!$commit) {
return new Aphront404Response();
}
$xactions = array();
$action = $request->getStr('action');
if ($action != PhabricatorAuditActionConstants::COMMENT) {
$action_xaction = id(new PhabricatorAuditTransaction())
->setAuthorPHID($viewer->getPHID())
->setObjectPHID($commit->getPHID())
->setTransactionType(PhabricatorAuditActionConstants::ACTION)
->setNewValue($action);
$auditors = $request->getStrList('auditors');
if ($action == PhabricatorAuditActionConstants::ADD_AUDITORS &&
$auditors) {
$action_xaction->setTransactionType($action);
$action_xaction->setNewValue(array_fuse($auditors));
}
$ccs = $request->getStrList('ccs');
if ($action == PhabricatorAuditActionConstants::ADD_CCS && $ccs) {
$action_xaction->setTransactionType(
PhabricatorTransactions::TYPE_SUBSCRIBERS);
// NOTE: This doesn't get processed before use, so just provide fake
// values.
$action_xaction->setOldValue(array());
$action_xaction->setNewValue($ccs);
}
$xactions[] = $action_xaction;
}
$content = $request->getStr('content');
if (strlen($content)) {
$xactions[] = id(new PhabricatorAuditTransaction())
->setAuthorPHID($viewer->getPHID())
->setObjectPHID($commit->getPHID())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->attachComment(
id(new PhabricatorAuditTransactionComment())
->setContent($content));
}
$phids = array();
foreach ($xactions as $xaction) {
$phids[] = $xaction->getRequiredHandlePHIDs();
}
$phids = array_mergev($phids);
$handles = $this->loadViewerHandles($phids);
foreach ($xactions as $xaction) {
$xaction->setHandles($handles);
}
$view = id(new PhabricatorAuditTransactionView())
->setIsPreview(true)
->setUser($viewer)
->setObjectPHID($commit->getPHID())
->setTransactions($xactions);
id(new PhabricatorDraft())
->setAuthorPHID($viewer->getPHID())
->setDraftKey('diffusion-audit-'.$id)
->setDraft($content)
->replaceOrDelete();
return id(new AphrontAjaxResponse())->setContent(hsprintf('%s', $view));
}
}

View file

@ -10,7 +10,7 @@ final class PhabricatorAuditEditor
private $rawPatch;
private $auditorPHIDs = array();
private $didExpandInlineState;
private $didExpandInlineState = false;
public function addAuditReason($phid, $reason) {
if (!isset($this->auditReasonMap[$phid])) {
@ -42,7 +42,7 @@ final class PhabricatorAuditEditor
}
public function getEditorApplicationClass() {
return 'PhabricatorAuditApplication';
return 'PhabricatorDiffusionApplication';
}
public function getEditorObjectsDescription() {
@ -67,6 +67,21 @@ final class PhabricatorAuditEditor
return $types;
}
protected function expandTransactions(
PhabricatorLiskDAO $object,
array $xactions) {
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_INLINESTATE:
$this->didExpandInlineState = true;
break;
}
}
return parent::expandTransactions($object, $xactions);
}
protected function transactionHasEffect(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {

View file

@ -4,7 +4,7 @@ final class PhabricatorAuditMailReceiver extends PhabricatorObjectMailReceiver {
public function isEnabled() {
return PhabricatorApplication::isClassInstalled(
'PhabricatorAuditApplication');
'PhabricatorDiffusionApplication');
}
protected function getObjectPattern() {

View file

@ -67,9 +67,6 @@ final class PhabricatorAuditManagementDeleteWorkflow
$ids = $this->parseList($args->getArg('ids'));
$status = $args->getArg('status');
if (!$status) {
$status = DiffusionCommitQuery::AUDIT_STATUS_OPEN;
}
$min_date = $this->loadDate($args->getArg('min-commit-date'));
$max_date = $this->loadDate($args->getArg('max-commit-date'));
@ -85,7 +82,7 @@ final class PhabricatorAuditManagementDeleteWorkflow
->needAuditRequests(true);
if ($status) {
$query->withAuditStatus($status);
$query->withStatuses(array($status));
}
$id_map = array();

View file

@ -17,23 +17,27 @@ final class PhabricatorCommitSearchEngine
->needCommitData(true);
}
protected function newResultBuckets() {
return DiffusionCommitResultBucket::getAllResultBuckets();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['needsAuditByPHIDs']) {
$query->withNeedsAuditByPHIDs($map['needsAuditByPHIDs']);
if ($map['responsiblePHIDs']) {
$query->withResponsiblePHIDs($map['responsiblePHIDs']);
}
if ($map['auditorPHIDs']) {
$query->withAuditorPHIDs($map['auditorPHIDs']);
}
if ($map['commitAuthorPHIDs']) {
$query->withAuthorPHIDs($map['commitAuthorPHIDs']);
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['auditStatus']) {
$query->withAuditStatus($map['auditStatus']);
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
if ($map['repositoryPHIDs']) {
@ -46,48 +50,47 @@ final class PhabricatorCommitSearchEngine
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Needs Audit By'))
->setKey('needsAuditByPHIDs')
->setAliases(array('needs', 'need'))
->setDatasource(new DiffusionAuditorFunctionDatasource()),
->setLabel(pht('Responsible Users'))
->setKey('responsiblePHIDs')
->setConduitKey('responsible')
->setAliases(array('responsible', 'responsibles', 'responsiblePHID'))
->setDatasource(new DifferentialResponsibleDatasource()),
id(new PhabricatorUsersSearchField())
->setLabel(pht('Authors'))
->setKey('authorPHIDs')
->setConduitKey('authors')
->setAliases(array('author', 'authors', 'authorPHID')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Auditors'))
->setKey('auditorPHIDs')
->setAliases(array('auditor', 'auditors'))
->setConduitKey('auditors')
->setAliases(array('auditor', 'auditors', 'auditorPHID'))
->setDatasource(new DiffusionAuditorFunctionDatasource()),
id(new PhabricatorUsersSearchField())
->setLabel(pht('Authors'))
->setKey('commitAuthorPHIDs')
->setAliases(array('author', 'authors')),
id(new PhabricatorSearchSelectField())
id(new PhabricatorSearchCheckboxesField())
->setLabel(pht('Audit Status'))
->setKey('auditStatus')
->setKey('statuses')
->setAliases(array('status'))
->setOptions($this->getAuditStatusOptions()),
->setOptions(PhabricatorAuditCommitStatusConstants::getStatusNameMap()),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Repositories'))
->setKey('repositoryPHIDs')
->setAliases(array('repository', 'repositories'))
->setConduitKey('repositories')
->setAliases(array('repository', 'repositories', 'repositoryPHID'))
->setDatasource(new DiffusionRepositoryDatasource()),
);
}
protected function getURI($path) {
return '/audit/'.$path;
return '/diffusion/commit/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['need'] = pht('Needs Audit');
$names['problem'] = pht('Problem Commits');
}
$names['open'] = pht('Open Audits');
if ($this->requireViewer()->isLoggedIn()) {
$names['authored'] = pht('Authored Commits');
$names['active'] = pht('Active Audits');
$names['authored'] = pht('Authored');
$names['audited'] = pht('Audited');
}
$names['all'] = pht('All Commits');
@ -101,76 +104,71 @@ final class PhabricatorCommitSearchEngine
$viewer = $this->requireViewer();
$viewer_phid = $viewer->getPHID();
$status_open = DiffusionCommitQuery::AUDIT_STATUS_OPEN;
switch ($query_key) {
case 'all':
return $query;
case 'open':
$query->setParameter('auditStatus', $status_open);
return $query;
case 'need':
$needs_tokens = array(
$viewer_phid,
'projects('.$viewer_phid.')',
'packages('.$viewer_phid.')',
);
case 'active':
$bucket_key = DiffusionCommitRequiredActionResultBucket::BUCKETKEY;
$query->setParameter('needsAuditByPHIDs', $needs_tokens);
$query->setParameter('auditStatus', $status_open);
$open = PhabricatorAuditCommitStatusConstants::getOpenStatusConstants();
$query
->setParameter('responsiblePHIDs', array($viewer_phid))
->setParameter('statuses', $open)
->setParameter('bucket', $bucket_key);
return $query;
case 'authored':
$query->setParameter('commitAuthorPHIDs', array($viewer->getPHID()));
$query
->setParameter('authorPHIDs', array($viewer_phid));
return $query;
case 'problem':
$query->setParameter('commitAuthorPHIDs', array($viewer->getPHID()));
$query->setParameter(
'auditStatus',
DiffusionCommitQuery::AUDIT_STATUS_CONCERN);
case 'audited':
$query
->setParameter('auditorPHIDs', array($viewer_phid));
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
private function getAuditStatusOptions() {
return array(
DiffusionCommitQuery::AUDIT_STATUS_ANY => pht('Any'),
DiffusionCommitQuery::AUDIT_STATUS_OPEN => pht('Open'),
DiffusionCommitQuery::AUDIT_STATUS_CONCERN => pht('Concern Raised'),
DiffusionCommitQuery::AUDIT_STATUS_ACCEPTED => pht('Accepted'),
DiffusionCommitQuery::AUDIT_STATUS_PARTIAL => pht('Partially Audited'),
);
}
protected function renderResultList(
array $commits,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($commits, 'PhabricatorRepositoryCommit');
$viewer = $this->requireViewer();
$nodata = pht('No matching audits.');
$view = id(new PhabricatorAuditListView())
->setUser($viewer)
->setCommits($commits)
->setAuthorityPHIDs(
PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($viewer))
->setNoDataString($nodata);
$phids = $view->getRequiredHandlePHIDs();
if ($phids) {
$handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs($phids)
->execute();
$bucket = $this->getResultBucket($query);
$template = id(new PhabricatorAuditListView())
->setViewer($viewer);
$views = array();
if ($bucket) {
$bucket->setViewer($viewer);
try {
$groups = $bucket->newResultGroups($query, $commits);
foreach ($groups as $group) {
$views[] = id(clone $template)
->setHeader($group->getName())
->setNoDataString($group->getNoDataString())
->setCommits($group->getObjects());
}
} catch (Exception $ex) {
$this->addError($ex->getMessage());
}
} else {
$handles = array();
$views[] = id(clone $template)
->setCommits($commits)
->setNoDataString(pht('No matching commits.'));
}
$view->setHandles($handles);
$list = $view->buildList();
if (count($views) == 1) {
$list = head($views)->buildList();
} else {
$list = $views;
}
$result = new PhabricatorApplicationSearchResultView();
$result->setContent($list);

View file

@ -68,7 +68,8 @@ final class PhabricatorAuditInlineComment
public static function loadDraftComments(
PhabricatorUser $viewer,
$commit_phid) {
$commit_phid,
$raw = false) {
$inlines = id(new DiffusionDiffInlineCommentQuery())
->setViewer($viewer)
@ -80,6 +81,10 @@ final class PhabricatorAuditInlineComment
->needReplyToComments(true)
->execute();
if ($raw) {
return $inlines;
}
return self::buildProxies($inlines);
}

View file

@ -1,7 +1,7 @@
<?php
final class PhabricatorAuditTransaction
extends PhabricatorApplicationTransaction {
extends PhabricatorModularTransaction {
const TYPE_COMMIT = 'audit:commit';
@ -20,6 +20,10 @@ final class PhabricatorAuditTransaction
return 'audit';
}
public function getBaseTransactionClass() {
return 'DiffusionCommitTransactionType';
}
public function getApplicationTransactionType() {
return PhabricatorRepositoryCommitPHIDType::TYPECONST;
}
@ -434,6 +438,18 @@ final class PhabricatorAuditTransaction
public function getMailTags() {
$tags = array();
switch ($this->getTransactionType()) {
case DiffusionCommitAcceptTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_ACTION_ACCEPT;
break;
case DiffusionCommitConcernTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_ACTION_CONCERN;
break;
case DiffusionCommitResignTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_ACTION_RESIGN;
break;
case DiffusionCommitAuditorsTransaction::TRANSACTIONTYPE:
$tags[] = self::MAILTAG_ADD_AUDITORS;
break;
case PhabricatorAuditActionConstants::ACTION:
switch ($this->getNewValue()) {
case PhabricatorAuditActionConstants::CONCERN:

View file

@ -3,23 +3,10 @@
final class PhabricatorAuditListView extends AphrontView {
private $commits;
private $handles;
private $authorityPHIDs = array();
private $header;
private $noDataString;
private $highlightedAudits;
public function setHandles(array $handles) {
assert_instances_of($handles, 'PhabricatorObjectHandle');
$this->handles = $handles;
return $this;
}
public function setAuthorityPHIDs(array $phids) {
$this->authorityPHIDs = $phids;
return $this;
}
public function setNoDataString($no_data_string) {
$this->noDataString = $no_data_string;
return $this;
@ -29,6 +16,15 @@ final class PhabricatorAuditListView extends AphrontView {
return $this->noDataString;
}
public function setHeader($header) {
$this->header = $header;
return $this;
}
public function getHeader() {
return $this->header;
}
/**
* These commits should have both commit data and audit requests attached.
*/
@ -42,28 +38,6 @@ final class PhabricatorAuditListView extends AphrontView {
return $this->commits;
}
public function getRequiredHandlePHIDs() {
$phids = array();
$commits = $this->getCommits();
foreach ($commits as $commit) {
$phids[$commit->getPHID()] = true;
$phids[$commit->getAuthorPHID()] = true;
$audits = $commit->getAudits();
foreach ($audits as $audit) {
$phids[$audit->getAuditorPHID()] = true;
}
}
return array_keys($phids);
}
private function getHandle($phid) {
$handle = idx($this->handles, $phid);
if (!$handle) {
throw new Exception(pht("No handle for '%s'!", $phid));
}
return $handle;
}
private function getCommitDescription($phid) {
if ($this->commits === null) {
return pht('(Unknown Commit)');
@ -96,62 +70,43 @@ final class PhabricatorAuditListView extends AphrontView {
}
public function buildList() {
$user = $this->getUser();
if (!$user) {
throw new Exception(
pht(
'You must %s before %s!',
'setUser()',
__FUNCTION__.'()'));
}
$viewer = $this->getViewer();
$rowc = array();
$handles = $viewer->loadHandles(mpull($this->commits, 'getPHID'));
$list = new PHUIObjectItemListView();
foreach ($this->commits as $commit) {
$commit_phid = $commit->getPHID();
$commit_handle = $this->getHandle($commit_phid);
$commit_handle = $handles[$commit_phid];
$committed = null;
$commit_name = $commit_handle->getName();
$commit_link = $commit_handle->getURI();
$commit_desc = $this->getCommitDescription($commit_phid);
$committed = phabricator_datetime($commit->getEpoch(), $user);
$committed = phabricator_datetime($commit->getEpoch(), $viewer);
$audits = mpull($commit->getAudits(), null, 'getAuditorPHID');
$auditors = array();
$reasons = array();
foreach ($audits as $audit) {
$auditor_phid = $audit->getAuditorPHID();
$auditors[$auditor_phid] =
$this->getHandle($auditor_phid)->renderLink();
$auditors[$auditor_phid] = $viewer->renderHandle($auditor_phid);
}
$auditors = phutil_implode_html(', ', $auditors);
$authority_audits = array_select_keys($audits, $this->authorityPHIDs);
if ($authority_audits) {
$audit = reset($authority_audits);
} else {
$audit = reset($audits);
}
if ($audit) {
$reasons = $audit->getAuditReasons();
$reasons = phutil_implode_html(', ', $reasons);
$status_code = $audit->getAuditStatus();
$status_text =
PhabricatorAuditStatusConstants::getStatusName($status_code);
$status_color =
PhabricatorAuditStatusConstants::getStatusColor($status_code);
$status_icon =
PhabricatorAuditStatusConstants::getStatusIcon($status_code);
} else {
$reasons = null;
$status_text = null;
$status_color = null;
$status_icon = null;
}
$status = $commit->getAuditStatus();
$status_text =
PhabricatorAuditCommitStatusConstants::getStatusName($status);
$status_color =
PhabricatorAuditCommitStatusConstants::getStatusColor($status);
$status_icon =
PhabricatorAuditCommitStatusConstants::getStatusIcon($status);
$author_phid = $commit->getAuthorPHID();
if ($author_phid) {
$author_name = $this->getHandle($author_phid)->renderLink();
$author_name = $viewer->renderHandle($author_phid);
} else {
$author_name = $commit->getCommitData()->getAuthorName();
}
@ -169,8 +124,7 @@ final class PhabricatorAuditListView extends AphrontView {
}
if ($status_color) {
$item->setStatusIcon(
$status_icon.' '.$status_color, $status_text);
$item->setStatusIcon($status_icon.' '.$status_color, $status_text);
}
$list->addItem($item);
@ -180,6 +134,10 @@ final class PhabricatorAuditListView extends AphrontView {
$list->setNoDataString($this->noDataString);
}
if ($this->header) {
$list->setHeader($this->header);
}
return $list;
}

View file

@ -3,7 +3,7 @@
final class PhabricatorAuditTransactionView
extends PhabricatorApplicationTransactionView {
private $pathMap;
private $pathMap = array();
public function setPathMap(array $path_map) {
$this->pathMap = $path_map;
@ -55,12 +55,17 @@ final class PhabricatorAuditTransactionView
$type_inline = PhabricatorAuditActionConstants::INLINE;
$group = $xaction->getTransactionGroup();
if ($xaction->getTransactionType() == $type_inline) {
array_unshift($group, $xaction);
} else {
$out[] = parent::renderTransactionContent($xaction);
}
if ($this->getIsPreview()) {
return $out;
}
if (!$group) {
return $out;
}
@ -76,48 +81,58 @@ final class PhabricatorAuditTransactionView
}
}
if ($inlines) {
// TODO: This should do something similar to sortAndGroupInlines() to get
// a stable ordering.
$inlines_by_path = array();
foreach ($inlines as $key => $inline) {
$comment = $inline->getComment();
if (!$comment) {
// TODO: Migrate these away? They probably do not exist on normal
// non-development installs.
unset($inlines[$key]);
continue;
}
$path_id = $comment->getPathID();
$inlines_by_path[$path_id][] = $inline;
$structs = array();
foreach ($inlines as $key => $inline) {
$comment = $inline->getComment();
if (!$comment) {
// TODO: Migrate these away? They probably do not exist on normal
// non-development installs.
unset($inlines[$key]);
continue;
}
$inline_view = new PhabricatorInlineSummaryView();
foreach ($inlines_by_path as $path_id => $group) {
$path = idx($this->pathMap, $path_id);
if ($path === null) {
continue;
}
$items = array();
foreach ($group as $inline) {
$comment = $inline->getComment();
$item = array(
'id' => $comment->getID(),
'line' => $comment->getLineNumber(),
'length' => $comment->getLineLength(),
'content' => parent::renderTransactionContent($inline),
);
$items[] = $item;
}
$inline_view->addCommentGroup($path, $items);
$path_id = $comment->getPathID();
$path = idx($this->pathMap, $path_id);
if ($path === null) {
continue;
}
$out[] = $inline_view;
$structs[] = array(
'inline' => $inline,
'path' => $path,
'sort' => (string)id(new PhutilSortVector())
->addString($path)
->addInt($comment->getLineNumber())
->addInt($comment->getLineLength())
->addInt($inline->getID()),
);
}
if (!$structs) {
return $out;
}
$structs = isort($structs, 'sort');
$structs = igroup($structs, 'path');
$inline_view = new PhabricatorInlineSummaryView();
foreach ($structs as $path => $group) {
$inlines = ipull($group, 'inline');
$items = array();
foreach ($inlines as $inline) {
$comment = $inline->getComment();
$items[] = array(
'id' => $comment->getID(),
'line' => $comment->getLineNumber(),
'length' => $comment->getLineLength(),
'content' => parent::renderTransactionContent($inline),
);
}
$inline_view->addCommentGroup($path, $items);
}
$out[] = $inline_view;
return $out;
}

View file

@ -79,28 +79,40 @@ final class PhabricatorDataCacheSpec extends PhabricatorCacheSpec {
}
private function initAPCCommonSpec() {
$mem = apc_sma_info();
$this->setTotalMemory($mem['num_seg'] * $mem['seg_size']);
$info = apc_cache_info('user');
$this->setUsedMemory($info['mem_size']);
$this->setEntryCount(count($info['cache_list']));
$cache = $info['cache_list'];
$state = array();
foreach ($cache as $item) {
$info = idx($item, 'info', '<unknown-key>');
$key = self::getKeyPattern($info);
if (empty($state[$key])) {
$state[$key] = array(
'max' => 0,
'total' => 0,
'count' => 0,
);
if (function_exists('apcu_sma_info')) {
$mem = apcu_sma_info();
$info = apcu_cache_info();
} else if (function_exists('apc_sma_info')) {
$mem = apc_sma_info();
$info = apc_cache_info('user');
} else {
$mem = null;
}
if ($mem) {
$this->setTotalMemory($mem['num_seg'] * $mem['seg_size']);
$this->setUsedMemory($info['mem_size']);
$this->setEntryCount(count($info['cache_list']));
$cache = $info['cache_list'];
$state = array();
foreach ($cache as $item) {
$info = idx($item, 'info', '<unknown-key>');
$key = self::getKeyPattern($info);
if (empty($state[$key])) {
$state[$key] = array(
'max' => 0,
'total' => 0,
'count' => 0,
);
}
$state[$key]['max'] = max($state[$key]['max'], $item['mem_size']);
$state[$key]['total'] += $item['mem_size'];
$state[$key]['count']++;
}
$state[$key]['max'] = max($state[$key]['max'], $item['mem_size']);
$state[$key]['total'] += $item['mem_size'];
$state[$key]['count']++;
}
$this->setCacheSummary($state);

View file

@ -192,6 +192,14 @@ final class CelerityDefaultPostprocessor
'sh-disabledtext' => '#a6a6a6',
'sh-disabledbackground' => '#f3f3f3',
// Diffs
'new-background' => '#eaffea',
'new-bright' => '#a6f3a6',
'old-background' => '#ffecec',
'old-bright' => '#f8cbcb',
'move-background' => '#fdf5d4',
'copy-background' => '#f1c40f',
// Background color for "most" themes.
'page.background' => '#f8f8fb',
'page.sidenav' => '#f0f0f2',

View file

@ -128,6 +128,13 @@ final class PhabricatorConduitConsoleController
$stability_label = pht('Deprecated Method');
$stability_info = nonempty($reason, pht('This method is deprecated.'));
break;
case ConduitAPIMethod::METHOD_STATUS_FROZEN:
$stability_icon = 'fa-archive grey';
$stability_label = pht('Frozen Method');
$stability_info = nonempty(
$reason,
pht('This method is frozen and will eventually be deprecated.'));
break;
default:
$stability_label = null;
break;

View file

@ -11,9 +11,10 @@ abstract class ConduitAPIMethod
private $viewer;
const METHOD_STATUS_STABLE = 'stable';
const METHOD_STATUS_UNSTABLE = 'unstable';
const METHOD_STATUS_DEPRECATED = 'deprecated';
const METHOD_STATUS_STABLE = 'stable';
const METHOD_STATUS_UNSTABLE = 'unstable';
const METHOD_STATUS_DEPRECATED = 'deprecated';
const METHOD_STATUS_FROZEN = 'frozen';
const SCOPE_NEVER = 'scope.never';
const SCOPE_ALWAYS = 'scope.always';

View file

@ -66,7 +66,8 @@ final class PhabricatorConduitMethodQuery
}
$status = array(
ConduitAPIMethod::METHOD_STATUS_STABLE => $this->isStable,
ConduitAPIMethod::METHOD_STATUS_STABLE => $this->isStable,
ConduitAPIMethod::METHOD_STATUS_FROZEN => $this->isStable,
ConduitAPIMethod::METHOD_STATUS_DEPRECATED => $this->isDeprecated,
ConduitAPIMethod::METHOD_STATUS_UNSTABLE => $this->isUnstable,
);

View file

@ -166,6 +166,10 @@ final class PhabricatorConduitSearchEngine
$item->addIcon('fa-warning', pht('Deprecated'));
$item->setStatusIcon('fa-warning red');
break;
case ConduitAPIMethod::METHOD_STATUS_FROZEN:
$item->addIcon('fa-archive', pht('Frozen'));
$item->setStatusIcon('fa-archive grey');
break;
}
$list->addItem($item);

View file

@ -40,7 +40,13 @@ final class PhabricatorPHPConfigSetupCheck extends PhabricatorSetupCheck {
->setMessage($message);
}
$raw_post_data = (int)ini_get('always_populate_raw_post_data');
if (version_compare(phpversion(), '7', '>=')) {
// This option was removed in PHP7.
$raw_post_data = -1;
} else {
$raw_post_data = (int)ini_get('always_populate_raw_post_data');
}
if ($raw_post_data != -1) {
$summary = pht(
'PHP setting "%s" should be set to "-1" to avoid deprecation '.

View file

@ -11,15 +11,16 @@ final class PhabricatorPHPPreflightSetupCheck extends PhabricatorSetupCheck {
}
protected function executeChecks() {
if (version_compare(phpversion(), 7, '>=')) {
if (version_compare(phpversion(), 7, '>=') &&
version_compare(phpversion(), 7.1, '<')) {
$message = pht(
'This version of Phabricator does not support PHP 7. You '.
'are running PHP %s.',
'This version of Phabricator does not support PHP 7.0. You '.
'are running PHP %s. Upgrade to PHP 7.1 or newer.',
phpversion());
$this->newIssue('php.version7')
->setIsFatal(true)
->setName(pht('PHP 7 Not Supported'))
->setName(pht('PHP 7.0 Not Supported'))
->setMessage($message)
->addLink(
'https://phurl.io/u/php7',

View file

@ -11,6 +11,16 @@ final class DifferentialCloseConduitAPIMethod
return pht('Close a Differential revision.');
}
public function getMethodStatus() {
return self::METHOD_STATUS_FROZEN;
}
public function getMethodStatusDescription() {
return pht(
'This method is frozen and will eventually be deprecated. New code '.
'should use "differential.revision.edit" instead.');
}
protected function defineParamTypes() {
return array(
'revisionID' => 'required int',

View file

@ -11,6 +11,16 @@ final class DifferentialCreateCommentConduitAPIMethod
return pht('Add a comment to a Differential revision.');
}
public function getMethodStatus() {
return self::METHOD_STATUS_FROZEN;
}
public function getMethodStatusDescription() {
return pht(
'This method is frozen and will eventually be deprecated. New code '.
'should use "differential.revision.edit" instead.');
}
protected function defineParamTypes() {
return array(
'revision_id' => 'required revisionid',

View file

@ -11,6 +11,16 @@ final class DifferentialCreateRevisionConduitAPIMethod
return pht('Create a new Differential revision.');
}
public function getMethodStatus() {
return self::METHOD_STATUS_FROZEN;
}
public function getMethodStatusDescription() {
return pht(
'This method is frozen and will eventually be deprecated. New code '.
'should use "differential.revision.edit" instead.');
}
protected function defineParamTypes() {
return array(
// TODO: Arcanist passes this; prevent fatals after D4191 until Conduit

View file

@ -11,6 +11,16 @@ final class DifferentialQueryConduitAPIMethod
return pht('Query Differential revisions which match certain criteria.');
}
public function getMethodStatus() {
return self::METHOD_STATUS_FROZEN;
}
public function getMethodStatusDescription() {
return pht(
'This method is frozen and will eventually be deprecated. New code '.
'should use "differential.revision.search" instead.');
}
protected function defineParamTypes() {
$hash_types = ArcanistDifferentialRevisionHash::getTypes();
$hash_const = $this->formatStringConstants($hash_types);

View file

@ -26,16 +26,27 @@ final class DifferentialQueryDiffsConduitAPIMethod
$ids = $request->getValue('ids', array());
$revision_ids = $request->getValue('revisionIDs', array());
$diffs = array();
if ($ids || $revision_ids) {
$diffs = id(new DifferentialDiffQuery())
->setViewer($request->getUser())
->withIDs($ids)
->withRevisionIDs($revision_ids)
->needChangesets(true)
->execute();
if (!$ids && !$revision_ids) {
// This method just returns nothing if you pass no constraints because
// pagination hadn't been invented yet in 2008 when this method was
// written.
return array();
}
$query = id(new DifferentialDiffQuery())
->setViewer($request->getUser())
->needChangesets(true);
if ($ids) {
$query->withIDs($ids);
}
if ($revision_ids) {
$query->withRevisionIDs($revision_ids);
}
$diffs = $query->execute();
return mpull($diffs, 'getDiffDict', 'getID');
}

View file

@ -11,6 +11,16 @@ final class DifferentialUpdateRevisionConduitAPIMethod
return pht('Update a Differential revision.');
}
public function getMethodStatus() {
return self::METHOD_STATUS_FROZEN;
}
public function getMethodStatusDescription() {
return pht(
'This method is frozen and will eventually be deprecated. New code '.
'should use "differential.revision.edit" instead.');
}
protected function defineParamTypes() {
return array(
'id' => 'required revisionid',

View file

@ -152,36 +152,23 @@ final class DifferentialInlineCommentEditController
protected function deleteComment(PhabricatorInlineCommentInterface $inline) {
$inline->openTransaction();
$inline->setIsDeleted(1)->save();
DifferentialDraft::deleteHasDraft(
$inline->getAuthorPHID(),
$inline->getRevisionPHID(),
$inline->getPHID());
$this->syncDraft();
$inline->saveTransaction();
}
protected function undeleteComment(
PhabricatorInlineCommentInterface $inline) {
$inline->openTransaction();
$inline->setIsDeleted(0)->save();
DifferentialDraft::markHasDraft(
$inline->getAuthorPHID(),
$inline->getRevisionPHID(),
$inline->getPHID());
$this->syncDraft();
$inline->saveTransaction();
}
protected function saveComment(PhabricatorInlineCommentInterface $inline) {
$inline->openTransaction();
$inline->save();
DifferentialDraft::markHasDraft(
$inline->getAuthorPHID(),
$inline->getRevisionPHID(),
$inline->getPHID());
$this->syncDraft();
$inline->saveTransaction();
}
@ -224,4 +211,14 @@ final class DifferentialInlineCommentEditController
$ids);
}
private function syncDraft() {
$viewer = $this->getViewer();
$revision = $this->loadRevision();
$revision->newDraftEngine()
->setObject($revision)
->setViewer($viewer)
->synchronize();
}
}

View file

@ -463,6 +463,7 @@ final class DifferentialRevisionViewController extends DifferentialController {
}
Javelin::initBehavior('differential-user-select');
Javelin::initBehavior('differential-keyboard-navigation');
$view = id(new PHUITwoColumnView())
->setHeader($header)

View file

@ -29,7 +29,7 @@ final class DifferentialRevisionEditEngine
return 'PhabricatorDifferentialApplication';
}
protected function supportsEditEngineConfiguration() {
public function isEngineConfigurable() {
return false;
}

View file

@ -18,6 +18,14 @@ final class DifferentialTransactionEditor
return pht('Differential Revisions');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this revision.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getDiffUpdateTransaction(array $xactions) {
$type_update = DifferentialTransaction::TYPE_UPDATE;

View file

@ -26,6 +26,19 @@ final class DifferentialDiffExtractionEngine extends Phobject {
public function newDiffFromCommit(PhabricatorRepositoryCommit $commit) {
$viewer = $this->getViewer();
// If we already have an unattached diff for this commit, just reuse it.
// This stops us from repeatedly generating diffs if something goes wrong
// later in the process. See T10968 for context.
$existing_diffs = id(new DifferentialDiffQuery())
->setViewer($viewer)
->withCommitPHIDs(array($commit->getPHID()))
->withHasRevision(false)
->needChangesets(true)
->execute();
if ($existing_diffs) {
return head($existing_diffs);
}
$repository = $commit->getRepository();
$identifier = $commit->getCommitIdentifier();
$monogram = $commit->getMonogram();
@ -73,6 +86,7 @@ final class DifferentialDiffExtractionEngine extends Phobject {
$diff = DifferentialDiff::newFromRawChanges($viewer, $changes)
->setRepositoryPHID($repository->getPHID())
->setCommitPHID($commit->getPHID())
->setCreationMethod('commit')
->setSourceControlSystem($repository->getVersionControlSystem())
->setLintStatus(DifferentialLintStatus::LINT_AUTO_SKIP)

View file

@ -0,0 +1,17 @@
<?php
final class DifferentialRevisionDraftEngine
extends PhabricatorDraftEngine {
protected function hasCustomDraftContent() {
$viewer = $this->getViewer();
$revision = $this->getObject();
$inlines = DifferentialTransactionQuery::loadUnsubmittedInlineComments(
$viewer,
$revision);
return (bool)$inlines;
}
}

View file

@ -33,16 +33,30 @@ final class DifferentialRevisionPHIDType extends PhabricatorPHIDType {
$revision = $objects[$phid];
$title = $revision->getTitle();
$id = $revision->getID();
$status = $revision->getStatus();
$monogram = $revision->getMonogram();
$uri = $revision->getURI();
$handle->setName("D{$id}");
$handle->setURI("/D{$id}");
$handle->setFullName("D{$id}: {$title}");
$handle
->setName($monogram)
->setURI($uri)
->setFullName("{$monogram}: {$title}");
if ($revision->isClosed()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
$status = $revision->getStatus();
$icon = DifferentialRevisionStatus::getRevisionStatusIcon($status);
$color = DifferentialRevisionStatus::getRevisionStatusColor($status);
$name = ArcanistDifferentialRevisionStatus::getNameForRevisionStatus(
$status);
$handle
->setStateIcon($icon)
->setStateColor($color)
->setStateName($name);
}
}

View file

@ -6,6 +6,8 @@ final class DifferentialDiffQuery
private $ids;
private $phids;
private $revisionIDs;
private $commitPHIDs;
private $hasRevision;
private $needChangesets = false;
private $needProperties;
@ -25,6 +27,16 @@ final class DifferentialDiffQuery
return $this;
}
public function withCommitPHIDs(array $phids) {
$this->commitPHIDs = $phids;
return $this;
}
public function withHasRevision($has_revision) {
$this->hasRevision = $has_revision;
return $this;
}
public function needChangesets($bool) {
$this->needChangesets = $bool;
return $this;
@ -108,27 +120,46 @@ final class DifferentialDiffQuery
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids) {
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->revisionIDs) {
if ($this->revisionIDs !== null) {
$where[] = qsprintf(
$conn,
'revisionID IN (%Ld)',
$this->revisionIDs);
}
if ($this->commitPHIDs !== null) {
$where[] = qsprintf(
$conn,
'commitPHID IN (%Ls)',
$this->commitPHIDs);
}
if ($this->hasRevision !== null) {
if ($this->hasRevision) {
$where[] = qsprintf(
$conn,
'revisionID IS NOT NULL');
} else {
$where[] = qsprintf(
$conn,
'revisionID IS NULL');
}
}
return $where;
}

View file

@ -473,15 +473,33 @@ final class DifferentialRevisionQuery
}
if ($this->needDrafts) {
$drafts = id(new DifferentialDraft())->loadAllWhere(
'authorPHID = %s AND objectPHID IN (%Ls)',
$viewer->getPHID(),
mpull($revisions, 'getPHID'));
$drafts = mgroup($drafts, 'getObjectPHID');
foreach ($revisions as $revision) {
$revision->attachDrafts(
$viewer,
idx($drafts, $revision->getPHID(), array()));
$viewer_phid = $viewer->getPHID();
$draft_type = PhabricatorObjectHasDraftEdgeType::EDGECONST;
if (!$viewer_phid) {
// Viewers without a valid PHID can never have drafts.
foreach ($revisions as $revision) {
$revision->attachHasDraft($viewer, false);
}
} else {
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($revisions, 'getPHID'))
->withEdgeTypes(
array(
$draft_type,
))
->withDestinationPHIDs(array($viewer_phid));
$edge_query->execute();
foreach ($revisions as $revision) {
$has_draft = (bool)$edge_query->getDestinationPHIDs(
array(
$revision->getPHID(),
));
$revision->attachHasDraft($viewer, $has_draft);
}
}
}
@ -621,12 +639,13 @@ final class DifferentialRevisionQuery
}
if ($this->draftAuthors) {
$differential_draft = new DifferentialDraft();
$joins[] = qsprintf(
$conn_r,
'JOIN %T has_draft ON has_draft.objectPHID = r.phid '.
'AND has_draft.authorPHID IN (%Ls)',
$differential_draft->getTableName(),
'JOIN %T has_draft ON has_draft.srcPHID = r.phid
AND has_draft.type = %s
AND has_draft.dstPHID IN (%Ls)',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorObjectHasDraftEdgeType::EDGECONST,
$this->draftAuthors);
}

View file

@ -13,6 +13,7 @@ final class DifferentialDiff
protected $revisionID;
protected $authorPHID;
protected $repositoryPHID;
protected $commitPHID;
protected $sourceMachine;
protected $sourcePath;
@ -62,6 +63,7 @@ final class DifferentialDiff
'branch' => 'text255?',
'bookmark' => 'text255?',
'repositoryUUID' => 'text64?',
'commitPHID' => 'phid?',
// T6203/NULLABILITY
// These should be non-null; all diffs should have a creation method
@ -73,6 +75,9 @@ final class DifferentialDiff
'revisionID' => array(
'columns' => array('revisionID'),
),
'key_commit' => array(
'columns' => array('commitPHID'),
),
),
) + parent::getConfiguration();
}

View file

@ -20,46 +20,4 @@ final class DifferentialDraft extends DifferentialDAO {
) + parent::getConfiguration();
}
public static function markHasDraft(
$author_phid,
$object_phid,
$draft_key) {
try {
id(new DifferentialDraft())
->setObjectPHID($object_phid)
->setAuthorPHID($author_phid)
->setDraftKey($draft_key)
->save();
} catch (AphrontDuplicateKeyQueryException $ex) {
// no worries
}
}
public static function deleteHasDraft(
$author_phid,
$object_phid,
$draft_key) {
$draft = id(new DifferentialDraft())->loadOneWhere(
'objectPHID = %s AND authorPHID = %s AND draftKey = %s',
$object_phid,
$author_phid,
$draft_key);
if ($draft) {
$draft->delete();
}
}
public static function deleteAllDrafts(
$author_phid,
$object_phid) {
$drafts = id(new DifferentialDraft())->loadAllWhere(
'objectPHID = %s AND authorPHID = %s',
$object_phid,
$author_phid);
foreach ($drafts as $draft) {
$draft->delete();
}
}
}

View file

@ -15,7 +15,8 @@ final class DifferentialRevision extends DifferentialDAO
PhabricatorDestructibleInterface,
PhabricatorProjectInterface,
PhabricatorFulltextInterface,
PhabricatorConduitResultInterface {
PhabricatorConduitResultInterface,
PhabricatorDraftInterface {
protected $title = '';
protected $originalTitle;
@ -488,12 +489,12 @@ final class DifferentialRevision extends DifferentialDAO
return $this;
}
public function getDrafts(PhabricatorUser $viewer) {
return $this->assertAttachedKey($this->drafts, $viewer->getPHID());
public function getHasDraft(PhabricatorUser $viewer) {
return $this->assertAttachedKey($this->drafts, $viewer->getCacheFragment());
}
public function attachDrafts(PhabricatorUser $viewer, array $drafts) {
$this->drafts[$viewer->getPHID()] = $drafts;
public function attachHasDraft(PhabricatorUser $viewer, $has_draft) {
$this->drafts[$viewer->getCacheFragment()] = $has_draft;
return $this;
}
@ -735,4 +736,12 @@ final class DifferentialRevision extends DifferentialDAO
return array();
}
/* -( PhabricatorDraftInterface )------------------------------------------ */
public function newDraftEngine() {
return new DifferentialRevisionDraftEngine();
}
}

View file

@ -92,7 +92,7 @@ final class DifferentialRevisionListView extends AphrontView {
'');
}
if ($revision->getDrafts($viewer)) {
if ($revision->getHasDraft($viewer)) {
$icons['draft'] = true;
}

View file

@ -26,6 +26,10 @@ final class DifferentialRevisionAbandonTransaction
return 500;
}
public function getActionName() {
return pht('Abandoned');
}
public function getCommandKeyword() {
return 'abandon';
}

View file

@ -26,6 +26,10 @@ final class DifferentialRevisionAcceptTransaction
return 500;
}
public function getActionName() {
return pht('Accepted');
}
public function getCommandKeyword() {
$accept_key = 'differential.enable-email-accept';
$allow_email_accept = PhabricatorEnv::getEnvConfig($accept_key);

View file

@ -35,6 +35,10 @@ abstract class DifferentialRevisionActionTransaction
return 1000;
}
public function getActionStrength() {
return 3;
}
public function getRevisionActionOrderVector() {
return id(new PhutilSortVector())
->addInt($this->getRevisionActionOrder());

View file

@ -26,6 +26,10 @@ final class DifferentialRevisionCloseTransaction
return 300;
}
public function getActionName() {
return pht('Closed');
}
public function generateOldValue($object) {
return $object->isClosed();
}

View file

@ -26,6 +26,10 @@ final class DifferentialRevisionCommandeerTransaction
return 700;
}
public function getActionName() {
return pht('Commandeered');
}
public function getCommandKeyword() {
return 'commandeer';
}

View file

@ -27,6 +27,10 @@ final class DifferentialRevisionPlanChangesTransaction
return 200;
}
public function getActionName() {
return pht('Planned Changes');
}
public function getCommandKeyword() {
return 'planchanges';
}

View file

@ -26,6 +26,10 @@ final class DifferentialRevisionReclaimTransaction
return 600;
}
public function getActionName() {
return pht('Reclaimed');
}
public function getCommandKeyword() {
return 'reclaim';
}

View file

@ -26,6 +26,10 @@ final class DifferentialRevisionRejectTransaction
return 600;
}
public function getActionName() {
return pht('Requested Changes');
}
public function getCommandKeyword() {
return 'request';
}

View file

@ -26,6 +26,10 @@ final class DifferentialRevisionReopenTransaction
return 400;
}
public function getActionName() {
return pht('Reopened');
}
public function generateOldValue($object) {
return !$object->isClosed();
}

View file

@ -22,6 +22,10 @@ final class DifferentialRevisionRequestReviewTransaction
return 200;
}
public function getActionName() {
return pht('Requested Review');
}
public function generateOldValue($object) {
$status_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
return ($object->getStatus() == $status_review);

View file

@ -30,6 +30,10 @@ final class DifferentialRevisionResignTransaction
return 'resign';
}
public function getActionName() {
return pht('Resigned');
}
public function getCommandAliases() {
return array();
}

View file

@ -24,7 +24,13 @@ final class DifferentialRevisionReviewersTransaction
// First, remove any reviewers we're getting rid of.
$rem = idx($value, '-', array());
$rem = $datasource->evaluateTokens($rem);
foreach ($rem as $phid) {
foreach ($rem as $spec) {
if (!is_array($spec)) {
$phid = $spec;
} else {
$phid = $spec['phid'];
}
unset($reviewers[$phid]);
}

View file

@ -28,6 +28,10 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication {
'name' => pht('Diffusion User Guide'),
'href' => PhabricatorEnv::getDoclink('Diffusion User Guide'),
),
array(
'name' => pht('Audit User Guide'),
'href' => PhabricatorEnv::getDoclink('Audit User Guide'),
),
);
}
@ -63,8 +67,6 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication {
=> 'DiffusionCommitBranchesController',
'commit/(?P<commit>[a-z0-9]+)/tags/'
=> 'DiffusionCommitTagsController',
'commit/(?P<commit>[a-z0-9]+)/edit/'
=> 'DiffusionCommitEditController',
'compare/' => 'DiffusionCompareController',
'manage/(?:(?P<panel>[^/]+)/)?'
=> 'DiffusionRepositoryManagePanelsController',
@ -131,6 +133,13 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication {
'symbol/(?P<name>[^/]+)/' => 'DiffusionSymbolController',
'external/' => 'DiffusionExternalController',
'lint/' => 'DiffusionLintController',
'commit/' => array(
$this->getQueryRoutePattern() =>
'DiffusionCommitListController',
$this->getEditRoutePattern('edit/') =>
'DiffusionCommitEditController',
),
),
);
}

View file

@ -0,0 +1,20 @@
<?php
final class DiffusionCommitEditConduitAPIMethod
extends PhabricatorEditEngineAPIMethod {
public function getAPIMethodName() {
return 'diffusion.commit.edit';
}
public function newEditEngine() {
return new DiffusionCommitEditEngine();
}
public function getMethodSummary() {
return pht(
'Apply transactions to edit an existing commit. This method can not '.
'create new commits.');
}
}

View file

@ -0,0 +1,18 @@
<?php
final class DiffusionCommitSearchConduitAPIMethod
extends PhabricatorSearchEngineAPIMethod {
public function getAPIMethodName() {
return 'diffusion.commit.search';
}
public function newSearchEngine() {
return new PhabricatorCommitSearchEngine();
}
public function getMethodSummary() {
return pht('Read information about commits.');
}
}

View file

@ -11,6 +11,16 @@ final class DiffusionQueryCommitsConduitAPIMethod
return pht('Retrieve information about commits.');
}
public function getMethodStatus() {
return self::METHOD_STATUS_FROZEN;
}
public function getMethodStatusDescription() {
return pht(
'This method is frozen and will eventually be deprecated. New code '.
'should use "diffusion.commit.search" instead.');
}
protected function defineReturnType() {
return 'map<string, dict>';
}

View file

@ -369,7 +369,9 @@ final class DiffusionCommitController extends DiffusionController {
}
$add_comment = $this->renderAddCommentPanel($commit, $audit_requests);
$add_comment = $this->renderAddCommentPanel(
$commit,
$timeline);
$filetree_on = $viewer->compareUserSetting(
PhabricatorShowFiletreeSetting::SETTINGKEY,
@ -717,150 +719,24 @@ final class DiffusionCommitController extends DiffusionController {
private function renderAddCommentPanel(
PhabricatorRepositoryCommit $commit,
array $audit_requests) {
assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest');
$timeline) {
$request = $this->getRequest();
$viewer = $request->getUser();
if (!$viewer->isLoggedIn()) {
return id(new PhabricatorApplicationTransactionCommentView())
->setUser($viewer)
->setRequestURI($request->getRequestURI());
}
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
$pane_id = celerity_generate_unique_node_id();
Javelin::initBehavior(
'differential-keyboard-navigation',
array(
'haunt' => $pane_id,
));
$draft = id(new PhabricatorDraft())->loadOneWhere(
'authorPHID = %s AND draftKey = %s',
$viewer->getPHID(),
'diffusion-audit-'.$commit->getID());
if ($draft) {
$draft = $draft->getDraft();
} else {
$draft = null;
}
$actions = $this->getAuditActions($commit, $audit_requests);
$mailable_source = new PhabricatorMetaMTAMailableDatasource();
$auditor_source = new DiffusionAuditorDatasource();
$form = id(new AphrontFormView())
->setUser($viewer)
->setAction('/audit/addcomment/')
->addHiddenInput('commit', $commit->getPHID())
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Action'))
->setName('action')
->setID('audit-action')
->setOptions($actions))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Add Auditors'))
->setName('auditors')
->setControlID('add-auditors')
->setControlStyle('display: none')
->setID('add-auditors-tokenizer')
->setDisableBehavior(true)
->setDatasource($auditor_source))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Add CCs'))
->setName('ccs')
->setControlID('add-ccs')
->setControlStyle('display: none')
->setID('add-ccs-tokenizer')
->setDisableBehavior(true)
->setDatasource($mailable_source))
->appendChild(
id(new PhabricatorRemarkupControl())
->setLabel(pht('Comments'))
->setName('content')
->setValue($draft)
->setID('audit-content')
->setUser($viewer))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Submit')));
$header = new PHUIHeaderView();
$header->setHeader(
$is_serious ? pht('Audit Commit') : pht('Creative Accounting'));
Javelin::initBehavior(
'differential-add-reviewers-and-ccs',
array(
'dynamic' => array(
'add-auditors-tokenizer' => array(
'actions' => array('add_auditors' => 1),
'src' => $auditor_source->getDatasourceURI(),
'row' => 'add-auditors',
'placeholder' => $auditor_source->getPlaceholderText(),
),
'add-ccs-tokenizer' => array(
'actions' => array('add_ccs' => 1),
'src' => $mailable_source->getDatasourceURI(),
'row' => 'add-ccs',
'placeholder' => $mailable_source->getPlaceholderText(),
),
),
'select' => 'audit-action',
));
Javelin::initBehavior('differential-feedback-preview', array(
'uri' => '/audit/preview/'.$commit->getID().'/',
'preview' => 'audit-preview',
'content' => 'audit-content',
'action' => 'audit-action',
'previewTokenizers' => array(
'auditors' => 'add-auditors-tokenizer',
'ccs' => 'add-ccs-tokenizer',
),
'inline' => 'inline-comment-preview',
'inlineuri' => '/diffusion/inline/preview/'.$commit->getPHID().'/',
));
$loading = phutil_tag_div(
'aphront-panel-preview-loading-text',
pht('Loading preview...'));
$preview_panel = phutil_tag_div(
'aphront-panel-preview aphront-panel-flush',
array(
phutil_tag('div', array('id' => 'audit-preview'), $loading),
phutil_tag('div', array('id' => 'inline-comment-preview')),
));
Javelin::initBehavior('differential-keyboard-navigation');
// TODO: This is pretty awkward, unify the CSS between Diffusion and
// Differential better.
require_celerity_resource('differential-core-view-css');
$anchor = id(new PhabricatorAnchorView())
->setAnchorName('comment')
->setNavigationMarker(true)
->render();
$comment_view = id(new DiffusionCommitEditEngine())
->setViewer($viewer)
->buildEditEngineCommentView($commit);
$comment_box = id(new PHUIObjectBoxView())
->setHeader($header)
->appendChild($form);
$comment_view->setTransactionTimeline($timeline);
return phutil_tag(
'div',
array(
'id' => $pane_id,
),
phutil_tag_div(
'differential-add-comment-panel',
array($anchor, $comment_box, $preview_panel)));
return $comment_view;
}
/**
@ -997,12 +873,12 @@ final class DiffusionCommitController extends DiffusionController {
$commit,
PhabricatorPolicyCapability::CAN_EDIT);
$identifier = $commit->getCommitIdentifier();
$uri = $repository->getPathURI("commit/{$identifier}/edit/");
$id = $commit->getID();
$edit_uri = $this->getApplicationURI("/commit/edit/{$id}/");
$action = id(new PhabricatorActionView())
->setName(pht('Edit Commit'))
->setHref($uri)
->setHref($edit_uri)
->setIcon('fa-pencil')
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit);

View file

@ -1,120 +1,12 @@
<?php
final class DiffusionCommitEditController extends DiffusionController {
final class DiffusionCommitEditController
extends DiffusionController {
public function handleRequest(AphrontRequest $request) {
$response = $this->loadDiffusionContext();
if ($response) {
return $response;
}
$viewer = $this->getViewer();
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$commit = $drequest->loadCommit();
if (!$commit) {
return new Aphront404Response();
}
$data = $commit->loadCommitData();
$page_title = pht('Edit Diffusion Commit');
$commit_phid = $commit->getPHID();
$edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$current_proj_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$commit_phid,
$edge_type);
if ($request->isFormPost()) {
$xactions = array();
$proj_phids = $request->getArr('projects');
$xactions[] = id(new PhabricatorAuditTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $edge_type)
->setNewValue(array('=' => array_fuse($proj_phids)));
$editor = id(new PhabricatorAuditEditor())
->setActor($viewer)
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request);
$editor->applyTransactions($commit, $xactions);
return id(new AphrontRedirectResponse())
->setURI($commit->getURI());
}
$tokenizer_id = celerity_generate_unique_node_id();
$form = id(new AphrontFormView())
->setUser($viewer)
->setAction($request->getRequestURI()->getPath())
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Projects'))
->setName('projects')
->setValue($current_proj_phids)
->setID($tokenizer_id)
->setDatasource(new PhabricatorProjectDatasource()));
$reason = $data->getCommitDetail('autocloseReason', false);
$reason = PhabricatorRepository::BECAUSE_AUTOCLOSE_FORCED;
if ($reason !== false) {
switch ($reason) {
case PhabricatorRepository::BECAUSE_REPOSITORY_IMPORTING:
$desc = pht('No, Repository Importing');
break;
case PhabricatorRepository::BECAUSE_AUTOCLOSE_DISABLED:
$desc = pht('No, Autoclose Disabled');
break;
case PhabricatorRepository::BECAUSE_NOT_ON_AUTOCLOSE_BRANCH:
$desc = pht('No, Not On Autoclose Branch');
break;
case PhabricatorRepository::BECAUSE_AUTOCLOSE_FORCED:
$desc = pht('Yes, Forced Via bin/repository CLI Tool.');
break;
case null:
$desc = pht('Yes');
break;
default:
$desc = pht('Unknown');
break;
}
$doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: Autoclose');
$doc_link = phutil_tag(
'a',
array(
'href' => $doc_href,
'target' => '_blank',
),
pht('Learn More'));
$form->appendChild(
id(new AphrontFormMarkupControl())
->setLabel(pht('Autoclose?'))
->setValue(array($desc, " \xC2\xB7 ", $doc_link)));
}
$form->appendControl(
id(new AphrontFormSubmitControl())
->setValue(pht('Save'))
->addCancelButton($commit->getURI()));
$crumbs = $this->buildCrumbs(
array(
'commit' => true,
));
$crumbs->addTextCrumb(pht('Edit'));
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($page_title)
->setForm($form);
return $this->newPage()
->setTitle($page_title)
->setCrumbs($crumbs)
->appendChild($form_box);
return id(new DiffusionCommitEditEngine())
->setController($this)
->buildResponse();
}
}

View file

@ -0,0 +1,26 @@
<?php
final class DiffusionCommitListController
extends DiffusionController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
return id(new PhabricatorCommitSearchEngine())
->setController($this)
->buildResponse();
}
protected function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
$crumbs->addTextCrumb(
pht('Commits'),
$this->getApplicationURI('commit/'));
return $crumbs;
}
}

View file

@ -7,8 +7,19 @@ final class DiffusionRepositoryListController extends DiffusionController {
}
public function handleRequest(AphrontRequest $request) {
$items = array();
$items[] = id(new PHUIListItemView())
->setType(PHUIListItemView::TYPE_LABEL)
->setName(pht('Commits'));
$items[] = id(new PHUIListItemView())
->setName('Browse Commits')
->setHref($this->getApplicationURI('commit/'));
return id(new PhabricatorRepositorySearchEngine())
->setController($this)
->setNavigationItems($items)
->buildResponse();
}

View file

@ -0,0 +1,233 @@
<?php
final class DiffusionCommitEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'diffusion.commit';
const ACTIONGROUP_AUDIT = 'audit';
const ACTIONGROUP_COMMIT = 'commit';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Commits');
}
public function getSummaryHeader() {
return pht('Edit Commits');
}
public function getSummaryText() {
return pht('Edit commits.');
}
public function getEngineApplicationClass() {
return 'PhabricatorDiffusionApplication';
}
protected function newEditableObject() {
// NOTE: We must return a valid object here so that things like Conduit
// documentation generation work. You can't actually create commits via
// EditEngine. This is enforced with a "No One" creation policy.
$repository = new PhabricatorRepository();
$data = new PhabricatorRepositoryCommitData();
return id(new PhabricatorRepositoryCommit())
->attachRepository($repository)
->attachCommitData($data)
->attachAudits(array());
}
protected function newObjectQuery() {
return id(new DiffusionCommitQuery())
->needCommitData(true)
->needAuditRequests(true);
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('commit/edit/');
}
protected function newCommentActionGroups() {
return array(
id(new PhabricatorEditEngineCommentActionGroup())
->setKey(self::ACTIONGROUP_AUDIT)
->setLabel(pht('Audit Actions')),
id(new PhabricatorEditEngineCommentActionGroup())
->setKey(self::ACTIONGROUP_COMMIT)
->setLabel(pht('Commit Actions')),
);
}
protected function getObjectCreateTitleText($object) {
return pht('Create Commit');
}
protected function getObjectCreateShortText() {
return pht('Create Commit');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Commit: %s', $object->getDisplayName());
}
protected function getObjectEditShortText($object) {
return $object->getDisplayName();
}
protected function getObjectName() {
return pht('Commit');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return PhabricatorPolicies::POLICY_NOONE;
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
$data = $object->getCommitData();
$fields = array();
$fields[] = id(new PhabricatorDatasourceEditField())
->setKey('auditors')
->setLabel(pht('Auditors'))
->setDatasource(new DiffusionAuditorDatasource())
->setUseEdgeTransactions(true)
->setTransactionType(
DiffusionCommitAuditorsTransaction::TRANSACTIONTYPE)
->setCommentActionLabel(pht('Change Auditors'))
->setDescription(pht('Auditors for this commit.'))
->setConduitDescription(pht('Change the auditors for this commit.'))
->setConduitTypeDescription(pht('New auditors.'))
->setValue($object->getAuditorPHIDsForEdit());
$reason = $data->getCommitDetail('autocloseReason', false);
$reason = PhabricatorRepository::BECAUSE_AUTOCLOSE_FORCED;
if ($reason !== false) {
switch ($reason) {
case PhabricatorRepository::BECAUSE_REPOSITORY_IMPORTING:
$desc = pht('No, Repository Importing');
break;
case PhabricatorRepository::BECAUSE_AUTOCLOSE_DISABLED:
$desc = pht('No, Autoclose Disabled');
break;
case PhabricatorRepository::BECAUSE_NOT_ON_AUTOCLOSE_BRANCH:
$desc = pht('No, Not On Autoclose Branch');
break;
case PhabricatorRepository::BECAUSE_AUTOCLOSE_FORCED:
$desc = pht('Yes, Forced Via bin/repository CLI Tool.');
break;
case null:
$desc = pht('Yes');
break;
default:
$desc = pht('Unknown');
break;
}
$doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: Autoclose');
$doc_link = phutil_tag(
'a',
array(
'href' => $doc_href,
'target' => '_blank',
),
pht('Learn More'));
$fields[] = id(new PhabricatorStaticEditField())
->setLabel(pht('Autoclose?'))
->setValue(array($desc, " \xC2\xB7 ", $doc_link));
}
$actions = DiffusionCommitActionTransaction::loadAllActions();
$actions = msortv($actions, 'getCommitActionOrderVector');
foreach ($actions as $key => $action) {
$fields[] = $action->newEditField($object, $viewer);
}
return $fields;
}
protected function newAutomaticCommentTransactions($object) {
$viewer = $this->getViewer();
$xactions = array();
$inlines = PhabricatorAuditInlineComment::loadDraftComments(
$viewer,
$object->getPHID(),
$raw = true);
$inlines = msort($inlines, 'getID');
foreach ($inlines as $inline) {
$xactions[] = $object->getApplicationTransactionTemplate()
->setTransactionType(PhabricatorAuditActionConstants::INLINE)
->attachComment($inline);
}
$viewer_phid = $viewer->getPHID();
$viewer_is_author = ($object->getAuthorPHID() == $viewer_phid);
if ($viewer_is_author) {
$state_map = PhabricatorTransactions::getInlineStateMap();
$inlines = id(new DiffusionDiffInlineCommentQuery())
->setViewer($viewer)
->withCommitPHIDs(array($object->getPHID()))
->withFixedStates(array_keys($state_map))
->execute();
if ($inlines) {
$old_value = mpull($inlines, 'getFixedState', 'getPHID');
$new_value = array();
foreach ($old_value as $key => $state) {
$new_value[$key] = $state_map[$state];
}
$xactions[] = $object->getApplicationTransactionTemplate()
->setTransactionType(PhabricatorTransactions::TYPE_INLINESTATE)
->setIgnoreOnNoEffect(true)
->setOldValue($old_value)
->setNewValue($new_value);
}
}
return $xactions;
}
protected function newCommentPreviewContent($object, array $xactions) {
$viewer = $this->getViewer();
$type_inline = PhabricatorAuditActionConstants::INLINE;
$inlines = array();
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() === $type_inline) {
$inlines[] = $xaction->getComment();
}
}
$content = array();
if ($inlines) {
$inline_preview = id(new PHUIDiffInlineCommentPreviewListView())
->setViewer($viewer)
->setInlineComments($inlines);
$content[] = phutil_tag(
'div',
array(
'id' => 'inline-comment-preview',
),
$inline_preview);
}
return $content;
}
}

View file

@ -104,12 +104,26 @@ final class HeraldCommitAdapter
public function getTriggerObjectPHIDs() {
$project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
return array_merge(
array(
$this->getRepository()->getPHID(),
$this->getPHID(),
),
$this->loadEdgePHIDs($project_type));
$repository_phid = $this->getRepository()->getPHID();
$commit_phid = $this->getObject()->getPHID();
$phids = array();
$phids[] = $commit_phid;
$phids[] = $repository_phid;
// NOTE: This is projects for the repository, not for the commit. When
// Herald evalutes, commits normally can not have any project tags yet.
$repository_project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$repository_phid,
$project_type);
foreach ($repository_project_phids as $phid) {
$phids[] = $phid;
}
$phids = array_unique($phids);
$phids = array_values($phids);
return $phids;
}
public function explainValidTriggerObjects() {

View file

@ -251,9 +251,8 @@ final class DiffusionRepositoryClusterEngine extends Phobject {
pht(
'Repository "%s" exists on more than one device, but no device '.
'has any repository version information. Phabricator can not '.
'guess which copy of the existing data is authoritative. Remove '.
'all but one device from service to mark the remaining device '.
'as the authority.',
'guess which copy of the existing data is authoritative. Promote '.
'a device or see "Ambigous Leaders" in the documentation.',
$repository->getDisplayName()));
}

View file

@ -11,22 +11,16 @@ final class DiffusionCommitQuery
private $repositoryIDs;
private $repositoryPHIDs;
private $identifierMap;
private $responsiblePHIDs;
private $statuses;
private $needAuditRequests;
private $auditIDs;
private $auditorPHIDs;
private $needsAuditByPHIDs;
private $auditStatus;
private $epochMin;
private $epochMax;
private $importing;
const AUDIT_STATUS_ANY = 'audit-status-any';
const AUDIT_STATUS_OPEN = 'audit-status-open';
const AUDIT_STATUS_CONCERN = 'audit-status-concern';
const AUDIT_STATUS_ACCEPTED = 'audit-status-accepted';
const AUDIT_STATUS_PARTIAL = 'audit-status-partial';
private $needCommitData;
public function withIDs(array $ids) {
@ -119,14 +113,22 @@ final class DiffusionCommitQuery
return $this;
}
public function withNeedsAuditByPHIDs(array $needs_phids) {
$this->needsAuditByPHIDs = $needs_phids;
public function withResponsiblePHIDs(array $responsible_phids) {
$this->responsiblePHIDs = $responsible_phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withAuditStatus($status) {
$this->auditStatus = $status;
return $this;
// TODO: Replace callers with `withStatuses()`.
return $this->withStatuses(
array(
$status,
));
}
public function withEpochRange($min, $max) {
@ -251,10 +253,7 @@ final class DiffusionCommitQuery
}
}
// TODO: This should just be `needAuditRequests`, not `shouldJoinAudits()`,
// but leave that for a future diff.
if ($this->needAuditRequests || $this->shouldJoinAudits()) {
if ($this->needAuditRequests) {
$requests = id(new PhabricatorRepositoryAuditRequest())->loadAllWhere(
'commitPHID IN (%Ls)',
mpull($commits, 'getPHID'));
@ -459,67 +458,30 @@ final class DiffusionCommitQuery
if ($this->auditIDs !== null) {
$where[] = qsprintf(
$conn,
'audit.id IN (%Ld)',
'auditor.id IN (%Ld)',
$this->auditIDs);
}
if ($this->auditorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'audit.auditorPHID IN (%Ls)',
'auditor.auditorPHID IN (%Ls)',
$this->auditorPHIDs);
}
if ($this->needsAuditByPHIDs !== null) {
if ($this->responsiblePHIDs !== null) {
$where[] = qsprintf(
$conn,
'needs.auditorPHID IN (%Ls)',
$this->needsAuditByPHIDs);
'(audit.auditorPHID IN (%Ls) OR commit.authorPHID IN (%Ls))',
$this->responsiblePHIDs,
$this->responsiblePHIDs);
}
$status = $this->auditStatus;
if ($status !== null) {
switch ($status) {
case self::AUDIT_STATUS_PARTIAL:
$where[] = qsprintf(
$conn,
'commit.auditStatus = %d',
PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED);
break;
case self::AUDIT_STATUS_ACCEPTED:
$where[] = qsprintf(
$conn,
'commit.auditStatus = %d',
PhabricatorAuditCommitStatusConstants::FULLY_AUDITED);
break;
case self::AUDIT_STATUS_CONCERN:
$where[] = qsprintf(
$conn,
'status.auditStatus = %s',
PhabricatorAuditStatusConstants::CONCERNED);
break;
case self::AUDIT_STATUS_OPEN:
$where[] = qsprintf(
$conn,
'status.auditStatus in (%Ls)',
PhabricatorAuditStatusConstants::getOpenStatusConstants());
break;
case self::AUDIT_STATUS_ANY:
break;
default:
$valid = array(
self::AUDIT_STATUS_ANY,
self::AUDIT_STATUS_OPEN,
self::AUDIT_STATUS_CONCERN,
self::AUDIT_STATUS_ACCEPTED,
self::AUDIT_STATUS_PARTIAL,
);
throw new Exception(
pht(
"Unknown audit status '%s'! Valid statuses are: %s.",
$status,
implode(', ', $valid)));
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'commit.auditStatus IN (%Ls)',
$this->statuses);
}
return $where;
@ -535,61 +497,41 @@ final class DiffusionCommitQuery
}
}
private function shouldJoinStatus() {
return $this->auditStatus;
private function shouldJoinAuditor() {
return ($this->auditIDs || $this->auditorPHIDs);
}
private function shouldJoinAudits() {
return $this->auditIDs || $this->auditorPHIDs;
}
private function shouldJoinNeeds() {
return $this->needsAuditByPHIDs;
private function shouldJoinAudit() {
return (bool)$this->responsiblePHIDs;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$join = parent::buildJoinClauseParts($conn);
$audit_request = new PhabricatorRepositoryAuditRequest();
if ($this->shouldJoinStatus()) {
if ($this->shouldJoinAuditor()) {
$join[] = qsprintf(
$conn,
'LEFT JOIN %T status ON commit.phid = status.commitPHID',
'JOIN %T auditor ON commit.phid = auditor.commitPHID',
$audit_request->getTableName());
}
if ($this->shouldJoinAudits()) {
if ($this->shouldJoinAudit()) {
$join[] = qsprintf(
$conn,
'JOIN %T audit ON commit.phid = audit.commitPHID',
'LEFT JOIN %T audit ON commit.phid = audit.commitPHID',
$audit_request->getTableName());
}
if ($this->shouldJoinNeeds()) {
$join[] = qsprintf(
$conn,
'JOIN %T needs ON commit.phid = needs.commitPHID
AND needs.auditStatus IN (%Ls)',
$audit_request->getTableName(),
array(
PhabricatorAuditStatusConstants::AUDIT_REQUESTED,
PhabricatorAuditStatusConstants::AUDIT_REQUIRED,
));
}
return $join;
}
protected function shouldGroupQueryResultRows() {
if ($this->shouldJoinStatus()) {
if ($this->shouldJoinAuditor()) {
return true;
}
if ($this->shouldJoinAudits()) {
return true;
}
if ($this->shouldJoinNeeds()) {
if ($this->shouldJoinAudit()) {
return true;
}

View file

@ -0,0 +1,151 @@
<?php
final class DiffusionCommitRequiredActionResultBucket
extends DiffusionCommitResultBucket {
const BUCKETKEY = 'action';
private $objects;
public function getResultBucketName() {
return pht('Bucket by Required Action');
}
protected function buildResultGroups(
PhabricatorSavedQuery $query,
array $objects) {
$this->objects = $objects;
$phids = $query->getEvaluatedParameter('responsiblePHIDs', array());
if (!$phids) {
throw new Exception(
pht(
'You can not bucket results by required action without '.
'specifying "Responsible Users".'));
}
$phids = array_fuse($phids);
$groups = array();
$groups[] = $this->newGroup()
->setName(pht('Needs Attention'))
->setNoDataString(pht('None of your commits have active concerns.'))
->setObjects($this->filterConcernRaised($phids));
$groups[] = $this->newGroup()
->setName(pht('Ready to Audit'))
->setNoDataString(pht('No commits are waiting for you to audit them.'))
->setObjects($this->filterShouldAudit($phids));
$groups[] = $this->newGroup()
->setName(pht('Waiting on Authors'))
->setNoDataString(pht('None of your audits are waiting on authors.'))
->setObjects($this->filterWaitingOnAuthors($phids));
$groups[] = $this->newGroup()
->setName(pht('Waiting on Auditors'))
->setNoDataString(pht('None of your commits are waiting on audit.'))
->setObjects($this->filterWaitingOnAuditors($phids));
// Because you can apply these buckets to queries which include revisions
// that have been closed, add an "Other" bucket if we still have stuff
// that didn't get filtered into any of the previous buckets.
if ($this->objects) {
$groups[] = $this->newGroup()
->setName(pht('Other Commits'))
->setObjects($this->objects);
}
return $groups;
}
private function filterConcernRaised(array $phids) {
$results = array();
$objects = $this->objects;
$status_concern = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
foreach ($objects as $key => $object) {
if (empty($phids[$object->getAuthorPHID()])) {
continue;
}
if ($object->getAuditStatus() != $status_concern) {
continue;
}
$results[$key] = $object;
unset($this->objects[$key]);
}
return $results;
}
private function filterShouldAudit(array $phids) {
$results = array();
$objects = $this->objects;
$should_audit = array(
PhabricatorAuditStatusConstants::AUDIT_REQUIRED,
PhabricatorAuditStatusConstants::AUDIT_REQUESTED,
);
$should_audit = array_fuse($should_audit);
foreach ($objects as $key => $object) {
if (!$this->hasAuditorsWithStatus($object, $phids, $should_audit)) {
continue;
}
$results[$key] = $object;
unset($this->objects[$key]);
}
return $results;
}
private function filterWaitingOnAuthors(array $phids) {
$results = array();
$objects = $this->objects;
$status_concern = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
foreach ($objects as $key => $object) {
if ($object->getAuditStatus() != $status_concern) {
continue;
}
if (isset($phids[$object->getAuthorPHID()])) {
continue;
}
$results[$key] = $object;
unset($this->objects[$key]);
}
return $results;
}
private function filterWaitingOnAuditors(array $phids) {
$results = array();
$objects = $this->objects;
$status_waiting = array(
PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT,
PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED,
);
$status_waiting = array_fuse($status_waiting);
foreach ($objects as $key => $object) {
if (empty($status_waiting[$object->getAuditStatus()])) {
continue;
}
$results[$key] = $object;
unset($this->objects[$key]);
}
return $results;
}
}

View file

@ -0,0 +1,33 @@
<?php
abstract class DiffusionCommitResultBucket
extends PhabricatorSearchResultBucket {
public static function getAllResultBuckets() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getResultBucketKey')
->execute();
}
protected function hasAuditorsWithStatus(
PhabricatorRepositoryCommit $commit,
array $phids,
array $statuses) {
foreach ($commit->getAudits() as $audit) {
if (!isset($phids[$audit->getAuditorPHID()])) {
continue;
}
if (!isset($statuses[$audit->getAuditStatus()])) {
continue;
}
return true;
}
return false;
}
}

View file

@ -35,6 +35,8 @@ final class DiffusionCloneURIView extends AphrontView {
}
public function render() {
$viewer = $this->getViewer();
require_celerity_resource('diffusion-icons-css');
Javelin::initBehavior('select-content');
@ -87,12 +89,18 @@ final class DiffusionCloneURIView extends AphrontView {
case PhabricatorRepositoryURI::IO_READWRITE:
switch ($uri->getBuiltinProtocol()) {
case PhabricatorRepositoryURI::BUILTIN_PROTOCOL_SSH:
$auth_uri = '/settings/panel/ssh/';
$auth_uri = id(new PhabricatorSSHKeysSettingsPanel())
->setViewer($viewer)
->setUser($viewer)
->getPanelURI();
$auth_tip = pht('Manage SSH Keys');
$auth_disabled = false;
break;
default:
$auth_uri = '/settings/panel/vcspassword';
$auth_uri = id(new DiffusionSetPasswordSettingsPanel())
->setViewer($viewer)
->setUser($viewer)
->getPanelURI();
$auth_tip = pht('Manage Password');
$auth_disabled = false;
break;

View file

@ -0,0 +1,78 @@
<?php
final class DiffusionCommitAcceptTransaction
extends DiffusionCommitAuditTransaction {
const TRANSACTIONTYPE = 'diffusion.commit.accept';
const ACTIONKEY = 'accept';
protected function getCommitActionLabel() {
return pht("Accept Commit \xE2\x9C\x94");
}
protected function getCommitActionDescription() {
return pht('This commit will be approved.');
}
public function getIcon() {
return 'fa-check-circle-o';
}
public function getColor() {
return 'green';
}
protected function getCommitActionOrder() {
return 500;
}
public function getActionName() {
return pht('Accepted');
}
public function generateOldValue($object) {
$actor = $this->getActor();
return $this->isViewerAcceptingAuditor($object, $actor);
}
public function applyExternalEffects($object, $value) {
$status = PhabricatorAuditStatusConstants::ACCEPTED;
$actor = $this->getActor();
$this->applyAuditorEffect($object, $actor, $value, $status);
}
protected function validateAction($object, PhabricatorUser $viewer) {
$config_key = 'audit.can-author-close-audit';
if (!PhabricatorEnv::getEnvConfig($config_key)) {
if ($this->isViewerCommitAuthor($object, $viewer)) {
throw new Exception(
pht(
'You can not accept this commit because you are the commit '.
'author. You can only accept commits you did not author. You can '.
'change this behavior by adjusting the "%s" setting in Config.',
$config_key));
}
}
if ($this->isViewerAcceptingAuditor($object, $viewer)) {
throw new Exception(
pht(
'You can not accept this commit because you have already '.
'accepted it.'));
}
}
public function getTitle() {
return pht(
'%s accepted this commit.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s accepted %s.',
$this->renderAuthor(),
$this->renderObject());
}
}

View file

@ -0,0 +1,118 @@
<?php
abstract class DiffusionCommitActionTransaction
extends DiffusionCommitTransactionType {
final public function getCommitActionKey() {
return $this->getPhobjectClassConstant('ACTIONKEY', 32);
}
public function isActionAvailable($object, PhabricatorUser $viewer) {
try {
$this->validateAction($object, $viewer);
return true;
} catch (Exception $ex) {
return false;
}
}
abstract protected function validateAction($object, PhabricatorUser $viewer);
abstract protected function getCommitActionLabel();
public function getCommandKeyword() {
return null;
}
public function getCommandAliases() {
return array();
}
public function getCommandSummary() {
return null;
}
protected function getCommitActionOrder() {
return 1000;
}
public function getCommitActionOrderVector() {
return id(new PhutilSortVector())
->addInt($this->getCommitActionOrder());
}
protected function getCommitActionGroupKey() {
return DiffusionCommitEditEngine::ACTIONGROUP_COMMIT;
}
protected function getCommitActionDescription() {
return null;
}
public static function loadAllActions() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getCommitActionKey')
->execute();
}
protected function isViewerCommitAuthor(
PhabricatorRepositoryCommit $commit,
PhabricatorUser $viewer) {
if (!$viewer->getPHID()) {
return false;
}
return ($viewer->getPHID() === $commit->getAuthorPHID());
}
public function newEditField(
PhabricatorRepositoryCommit $commit,
PhabricatorUser $viewer) {
$field = id(new PhabricatorApplyEditField())
->setKey($this->getCommitActionKey())
->setTransactionType($this->getTransactionTypeConstant())
->setValue(true);
if ($this->isActionAvailable($commit, $viewer)) {
$label = $this->getCommitActionLabel();
if ($label !== null) {
$field->setCommentActionLabel($label);
$description = $this->getCommitActionDescription();
$field->setActionDescription($description);
$group_key = $this->getCommitActionGroupKey();
$field->setCommentActionGroupKey($group_key);
$field->setActionConflictKey('commit.action');
}
}
return $field;
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$actor = $this->getActor();
$action_exception = null;
try {
$this->validateAction($object, $actor);
} catch (Exception $ex) {
$action_exception = $ex;
}
foreach ($xactions as $xaction) {
if ($action_exception) {
$errors[] = $this->newInvalidError(
$action_exception->getMessage(),
$xaction);
}
}
return $errors;
}
}

View file

@ -0,0 +1,118 @@
<?php
abstract class DiffusionCommitAuditTransaction
extends DiffusionCommitActionTransaction {
protected function getCommitActionGroupKey() {
return DiffusionCommitEditEngine::ACTIONGROUP_AUDIT;
}
protected function isViewerAnyAuditor(
PhabricatorRepositoryCommit $commit,
PhabricatorUser $viewer) {
return ($this->getViewerAuditStatus($commit, $viewer) !== null);
}
protected function isViewerAnyActiveAuditor(
PhabricatorRepositoryCommit $commit,
PhabricatorUser $viewer) {
// This omits various inactive states like "Resigned" and "Not Required".
return $this->isViewerAuditStatusAmong(
$commit,
$viewer,
array(
PhabricatorAuditStatusConstants::AUDIT_REQUIRED,
PhabricatorAuditStatusConstants::CONCERNED,
PhabricatorAuditStatusConstants::ACCEPTED,
PhabricatorAuditStatusConstants::AUDIT_REQUESTED,
));
}
protected function isViewerAcceptingAuditor(
PhabricatorRepositoryCommit $commit,
PhabricatorUser $viewer) {
return $this->isViewerAuditStatusAmong(
$commit,
$viewer,
array(
PhabricatorAuditStatusConstants::ACCEPTED,
));
}
protected function isViewerRejectingAuditor(
PhabricatorRepositoryCommit $commit,
PhabricatorUser $viewer) {
return $this->isViewerAuditStatusAmong(
$commit,
$viewer,
array(
PhabricatorAuditStatusConstants::CONCERNED,
));
}
protected function getViewerAuditStatus(
PhabricatorRepositoryCommit $commit,
PhabricatorUser $viewer) {
if (!$viewer->getPHID()) {
return null;
}
foreach ($commit->getAudits() as $audit) {
if ($audit->getAuditorPHID() != $viewer->getPHID()) {
continue;
}
return $audit->getAuditStatus();
}
return null;
}
protected function isViewerAuditStatusAmong(
PhabricatorRepositoryCommit $commit,
PhabricatorUser $viewer,
array $status_list) {
$status = $this->getViewerAuditStatus($commit, $viewer);
if ($status === null) {
return false;
}
$status_map = array_fuse($status_list);
return isset($status_map[$status]);
}
protected function applyAuditorEffect(
PhabricatorRepositoryCommit $commit,
PhabricatorUser $viewer,
$value,
$status) {
$audits = $commit->getAudits();
$audits = mpull($audits, null, 'getAuditorPHID');
$map = array();
$with_authority = ($status != PhabricatorAuditStatusConstants::RESIGNED);
if ($with_authority) {
$has_authority = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser(
$viewer);
$has_authority = array_fuse($has_authority);
foreach ($audits as $audit) {
$auditor_phid = $audit->getAuditorPHID();
if (isset($has_authority[$auditor_phid])) {
$map[$auditor_phid] = $status;
}
}
}
// In all cases, you affect yourself.
$map[$viewer->getPHID()] = $status;
$this->updateAudits($commit, $map);
}
}

View file

@ -0,0 +1,216 @@
<?php
final class DiffusionCommitAuditorsTransaction
extends DiffusionCommitTransactionType {
const TRANSACTIONTYPE = 'diffusion.commit.auditors';
public function generateOldValue($object) {
$auditors = $object->getAudits();
return mpull($auditors, 'getAuditStatus', 'getAuditorPHID');
}
public function generateNewValue($object, $value) {
$actor = $this->getActor();
$auditors = $this->generateOldValue($object);
$old_auditors = $auditors;
$request_status = PhabricatorAuditStatusConstants::AUDIT_REQUESTED;
$rem = idx($value, '-', array());
foreach ($rem as $phid) {
unset($auditors[$phid]);
}
$add = idx($value, '+', array());
$add_map = array();
foreach ($add as $phid) {
$add_map[$phid] = $request_status;
}
$set = idx($value, '=', null);
if ($set !== null) {
foreach ($set as $phid) {
$add_map[$phid] = $request_status;
}
$auditors = array();
}
foreach ($add_map as $phid => $new_status) {
$old_status = idx($old_auditors, $phid);
if ($old_status) {
$auditors[$phid] = $old_status;
continue;
}
$auditors[$phid] = $new_status;
}
return $auditors;
}
public function getTransactionHasEffect($object, $old, $new) {
ksort($old);
ksort($new);
return ($old !== $new);
}
public function applyExternalEffects($object, $value) {
$src_phid = $object->getPHID();
$old = $this->generateOldValue($object);
$new = $value;
$auditors = $object->getAudits();
$auditors = mpull($auditors, null, 'getAuditorPHID');
$rem = array_diff_key($old, $new);
foreach ($rem as $phid => $status) {
$auditor = idx($auditors, $phid);
if ($auditor) {
$auditor->delete();
}
}
$this->updateAudits($object, $new);
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$rem = array_diff_key($old, $new);
$add = array_diff_key($new, $old);
$rem_phids = array_keys($rem);
$add_phids = array_keys($add);
$total_count = count($rem) + count($add);
if ($rem && $add) {
return pht(
'%s edited %s auditor(s), removed %s: %s; added %s: %s.',
$this->renderAuthor(),
new PhutilNumber($total_count),
phutil_count($rem_phids),
$this->renderHandleList($rem_phids),
phutil_count($add_phids),
$this->renderHandleList($add_phids));
} else if ($add) {
return pht(
'%s added %s auditor(s): %s.',
$this->renderAuthor(),
phutil_count($add_phids),
$this->renderHandleList($add_phids));
} else {
return pht(
'%s removed %s auditor(s): %s.',
$this->renderAuthor(),
phutil_count($rem_phids),
$this->renderHandleList($rem_phids));
}
}
public function getTitleForFeed() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$rem = array_diff_key($old, $new);
$add = array_diff_key($new, $old);
$rem_phids = array_keys($rem);
$add_phids = array_keys($add);
$total_count = count($rem) + count($add);
if ($rem && $add) {
return pht(
'%s edited %s auditor(s) for %s, removed %s: %s; added %s: %s.',
$this->renderAuthor(),
new PhutilNumber($total_count),
$this->renderObject(),
phutil_count($rem_phids),
$this->renderHandleList($rem_phids),
phutil_count($add_phids),
$this->renderHandleList($add_phids));
} else if ($add) {
return pht(
'%s added %s auditor(s) for %s: %s.',
$this->renderAuthor(),
phutil_count($add_phids),
$this->renderObject(),
$this->renderHandleList($add_phids));
} else {
return pht(
'%s removed %s auditor(s) for %s: %s.',
$this->renderAuthor(),
phutil_count($rem_phids),
$this->renderObject(),
$this->renderHandleList($rem_phids));
}
}
public function validateTransactions($object, array $xactions) {
$actor = $this->getActor();
$errors = array();
if (!$xactions) {
return $errors;
}
$author_phid = $object->getAuthorPHID();
$can_author_close_key = 'audit.can-author-close-audit';
$can_author_close = PhabricatorEnv::getEnvConfig($can_author_close_key);
$old = $this->generateOldValue($object);
foreach ($xactions as $xaction) {
$new = $this->generateNewValue($object, $xaction->getNewValue());
$add = array_diff_key($new, $old);
if (!$add) {
continue;
}
$objects = id(new PhabricatorObjectQuery())
->setViewer($actor)
->withPHIDs(array_keys($add))
->execute();
$objects = mpull($objects, null, 'getPHID');
foreach ($add as $phid => $status) {
if (!isset($objects[$phid])) {
$errors[] = $this->newInvalidError(
pht(
'Auditor "%s" is not a valid object.',
$phid),
$xaction);
continue;
}
switch (phid_get_type($phid)) {
case PhabricatorPeopleUserPHIDType::TYPECONST:
case PhabricatorOwnersPackagePHIDType::TYPECONST:
case PhabricatorProjectProjectPHIDType::TYPECONST:
break;
default:
$errors[] = $this->newInvalidError(
pht(
'Auditor "%s" must be a user, a package, or a project.',
$phid),
$xaction);
continue 2;
}
$is_self = ($phid === $author_phid);
if ($is_self && !$can_author_close) {
$errors[] = $this->newInvalidError(
pht('The author of a commit can not be an auditor.'),
$xaction);
continue;
}
}
}
return $errors;
}
}

View file

@ -0,0 +1,74 @@
<?php
final class DiffusionCommitConcernTransaction
extends DiffusionCommitAuditTransaction {
const TRANSACTIONTYPE = 'diffusion.commit.concern';
const ACTIONKEY = 'concern';
protected function getCommitActionLabel() {
return pht("Raise Concern \xE2\x9C\x98");
}
protected function getCommitActionDescription() {
return pht('This commit will be returned to the author for consideration.');
}
public function getIcon() {
return 'fa-times-circle-o';
}
public function getColor() {
return 'red';
}
protected function getCommitActionOrder() {
return 600;
}
public function getActionName() {
return pht('Raised Concern');
}
public function generateOldValue($object) {
$actor = $this->getActor();
return $this->isViewerRejectingAuditor($object, $actor);
}
public function applyExternalEffects($object, $value) {
$status = PhabricatorAuditStatusConstants::CONCERNED;
$actor = $this->getActor();
$this->applyAuditorEffect($object, $actor, $value, $status);
}
protected function validateAction($object, PhabricatorUser $viewer) {
if ($this->isViewerCommitAuthor($object, $viewer)) {
throw new Exception(
pht(
'You can not raise a concern with this commit because you are '.
'the commit author. You can only raise concerns with commits '.
'you did not author.'));
}
if ($this->isViewerRejectingAuditor($object, $viewer)) {
throw new Exception(
pht(
'You can not raise a concern with this commit because you have '.
'already raised a concern with it.'));
}
}
public function getTitle() {
return pht(
'%s raised a concern with this commit.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s raised a concern with %s.',
$this->renderAuthor(),
$this->renderObject());
}
}

View file

@ -0,0 +1,66 @@
<?php
final class DiffusionCommitResignTransaction
extends DiffusionCommitAuditTransaction {
const TRANSACTIONTYPE = 'diffusion.commit.resign';
const ACTIONKEY = 'resign';
protected function getCommitActionLabel() {
return pht('Resign as Auditor');
}
protected function getCommitActionDescription() {
return pht('You will resign as an auditor for this commit.');
}
public function getIcon() {
return 'fa-flag';
}
public function getColor() {
return 'orange';
}
protected function getCommitActionOrder() {
return 700;
}
public function getActionName() {
return pht('Resigned');
}
public function generateOldValue($object) {
$actor = $this->getActor();
return !$this->isViewerAnyActiveAuditor($object, $actor);
}
public function applyExternalEffects($object, $value) {
$status = PhabricatorAuditStatusConstants::RESIGNED;
$actor = $this->getActor();
$this->applyAuditorEffect($object, $actor, $value, $status);
}
protected function validateAction($object, PhabricatorUser $viewer) {
if (!$this->isViewerAnyActiveAuditor($object, $viewer)) {
throw new Exception(
pht(
'You can not resign from this commit because you are not an '.
'active auditor.'));
}
}
public function getTitle() {
return pht(
'%s resigned from this commit.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s resigned from %s.',
$this->renderAuthor(),
$this->renderObject());
}
}

View file

@ -0,0 +1,37 @@
<?php
abstract class DiffusionCommitTransactionType
extends PhabricatorModularTransactionType {
protected function updateAudits(
PhabricatorRepositoryCommit $commit,
array $new) {
$audits = $commit->getAudits();
$audits = mpull($audits, null, 'getAuditorPHID');
foreach ($new as $phid => $status) {
$audit = idx($audits, $phid);
if (!$audit) {
$audit = id(new PhabricatorRepositoryAuditRequest())
->setAuditorPHID($phid)
->setCommitPHID($commit->getPHID());
$audits[$phid] = $audit;
} else {
if ($audit->getAuditStatus() === $status) {
continue;
}
}
$audit
->setAuditStatus($status)
->save();
}
$commit->attachAudits($audits);
return $audits;
}
}

View file

@ -0,0 +1,39 @@
<?php
final class PhabricatorFavoritesApplication extends PhabricatorApplication {
public function getBaseURI() {
return '/favorites/';
}
public function getName() {
return pht('Favorites');
}
public function getShortDescription() {
return pht('Favorite Items');
}
public function getIcon() {
return 'fa-star-o';
}
public function getRoutes() {
return array(
'/favorites/' => array(
'' => 'PhabricatorFavoritesMainController',
'(?P<type>global|personal)/item/' => $this->getProfileMenuRouting(
'PhabricatorFavoritesMenuItemController'),
),
);
}
public function isLaunchable() {
return false;
}
public function getApplicationOrder() {
return 9;
}
}

View file

@ -0,0 +1,11 @@
<?php
final class PhabricatorFavoritesConstants
extends PhabricatorFavoritesController {
const ITEM_TASK = 'favorites.task';
const ITEM_PROJECT = 'favorites.project';
const ITEM_REPOSITORY = 'favorites.repository';
const ITEM_MANAGE = 'favorites.manage';
}

View file

@ -0,0 +1,3 @@
<?php
abstract class PhabricatorFavoritesController extends PhabricatorController {}

View file

@ -0,0 +1,58 @@
<?php
final class PhabricatorFavoritesMainController
extends PhabricatorFavoritesController {
public function shouldAllowPublic() {
return false;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$menu = id(new PHUIObjectItemListView())
->setUser($viewer);
$menu->addItem(
id(new PHUIObjectItemView())
->setHeader(pht('Personal Menu Items'))
->setHref($this->getApplicationURI('personal/item/configure/'))
->setImageURI($viewer->getProfileImageURI())
->addAttribute(pht('Edit favorites for your personal account.')));
$icon = id(new PHUIIconView())
->setIcon('fa-globe')
->setBackground('bg-blue');
$menu->addItem(
id(new PHUIObjectItemView())
->setHeader(pht('Global Menu Items'))
->setHref($this->getApplicationURI('global/item/configure/'))
->setImageIcon($icon)
->addAttribute(pht('Edit global default favorites for all users.')));
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Manage'));
$crumbs->setBorder(true);
$box = id(new PHUIObjectBoxView())
->setObjectList($menu);
$header = id(new PHUIHeaderView())
->setHeader(pht('Manage Favorites'))
->setHeaderIcon('fa-star-o');
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter(array(
$box,
));
return $this->newPage()
->setTitle(pht('Manage'))
->setCrumbs($crumbs)
->appendChild($view);
}
}

View file

@ -0,0 +1,29 @@
<?php
final class PhabricatorFavoritesMenuItemController
extends PhabricatorFavoritesController {
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$type = $request->getURIData('type');
$custom_phid = null;
if ($type == 'personal') {
$custom_phid = $viewer->getPHID();
}
$application = 'PhabricatorFavoritesApplication';
$favorites = id(new PhabricatorApplicationQuery())
->setViewer($viewer)
->withClasses(array($application))
->withInstalled(true)
->executeOne();
$engine = id(new PhabricatorFavoritesProfileMenuEngine())
->setProfileObject($favorites)
->setCustomPHID($custom_phid)
->setController($this);
return $engine->buildResponse();
}
}

View file

@ -0,0 +1,70 @@
<?php
final class PhabricatorFavoritesProfileMenuEngine
extends PhabricatorProfileMenuEngine {
protected function isMenuEngineConfigurable() {
return true;
}
protected function getItemURI($path) {
$object = $this->getProfileObject();
$custom = $this->getCustomPHID();
if ($custom) {
return "/favorites/personal/item/{$path}";
} else {
return "/favorites/global/item/{$path}";
}
}
protected function getBuiltinProfileItems($object) {
$items = array();
$custom_phid = $this->getCustomPHID();
// Built-in Global Defaults
if (!$custom_phid) {
$create_task = array(
'name' => null,
'formKey' =>
id(new ManiphestEditEngine())->getProfileMenuItemDefault(),
);
$create_project = array(
'name' => null,
'formKey' =>
id(new PhabricatorProjectEditEngine())->getProfileMenuItemDefault(),
);
$create_repository = array(
'name' => null,
'formKey' =>
id(new DiffusionRepositoryEditEngine())->getProfileMenuItemDefault(),
);
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_TASK)
->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY)
->setMenuItemProperties($create_task);
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_PROJECT)
->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY)
->setMenuItemProperties($create_project);
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_REPOSITORY)
->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY)
->setMenuItemProperties($create_repository);
}
// Single Manage Item, switches URI based on admin/user
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_MANAGE)
->setMenuItemKey(
PhabricatorFavoritesManageProfileMenuItem::MENUITEMKEY);
return $items;
}
}

View file

@ -0,0 +1,72 @@
<?php
final class PhabricatorFavoritesManageProfileMenuItem
extends PhabricatorProfileMenuItem {
const MENUITEMKEY = 'favorites.manage';
public function getMenuItemTypeName() {
return pht('Manage Favorites');
}
private function getDefaultName() {
return pht('Manage');
}
public function canHideMenuItem(
PhabricatorProfileMenuItemConfiguration $config) {
return false;
}
public function canMakeDefault(
PhabricatorProfileMenuItemConfiguration $config) {
return false;
}
public function getDisplayName(
PhabricatorProfileMenuItemConfiguration $config) {
$name = $config->getMenuItemProperty('name');
if (strlen($name)) {
return $name;
}
return $this->getDefaultName();
}
public function buildEditEngineFields(
PhabricatorProfileMenuItemConfiguration $config) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setPlaceholder($this->getDefaultName())
->setValue($config->getMenuItemProperty('name')),
);
}
protected function newNavigationMenuItems(
PhabricatorProfileMenuItemConfiguration $config) {
$viewer = $this->getViewer();
if ($viewer->isLoggedIn()) {
$admin = $viewer->getIsAdmin();
$name = $this->getDisplayName($config);
$icon = 'fa-pencil';
$href = '/favorites/personal/item/configure/';
if ($admin) {
$href = '/favorites/';
}
$item = $this->newItem()
->setHref($href)
->setName($name)
->setIcon($icon);
}
return array(
$item,
);
}
}

View file

@ -27,6 +27,11 @@ final class PhabricatorHomeApplication extends PhabricatorApplication {
'/(?P<only>home)/' => 'PhabricatorHomeMainController',
'/home/' => array(
'create/' => 'PhabricatorHomeQuickCreateController',
'menu/' => array(
'' => 'PhabricatorHomeMenuController',
'(?P<type>global|personal)/item/' => $this->getProfileMenuRouting(
'PhabricatorHomeMenuItemController'),
),
),
);
}

View file

@ -0,0 +1,9 @@
<?php
final class PhabricatorHomeConstants
extends PhabricatorHomeController {
const ITEM_LAUNCHER = 'home.launcher';
const ITEM_MANAGE = 'home.manage.menu';
}

View file

@ -0,0 +1,57 @@
<?php
final class PhabricatorHomeMenuController extends PhabricatorHomeController {
public function shouldAllowPublic() {
return false;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$menu = id(new PHUIObjectItemListView())
->setUser($viewer);
$menu->addItem(
id(new PHUIObjectItemView())
->setHeader(pht('Personal Menu Items'))
->setHref($this->getApplicationURI('menu/personal/item/configure/'))
->setImageURI($viewer->getProfileImageURI())
->addAttribute(pht('Edit the menu for your personal account.')));
$icon = id(new PHUIIconView())
->setIcon('fa-globe')
->setBackground('bg-blue');
$menu->addItem(
id(new PHUIObjectItemView())
->setHeader(pht('Global Menu Items'))
->setHref($this->getApplicationURI('menu/global/item/configure/'))
->setImageIcon($icon)
->addAttribute(pht('Edit the global default menu for all users.')));
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Manage'));
$crumbs->setBorder(true);
$box = id(new PHUIObjectBoxView())
->setObjectList($menu);
$header = id(new PHUIHeaderView())
->setHeader(pht('Manage Home Menu'))
->setHeaderIcon('fa-home');
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter(array(
$box,
));
return $this->newPage()
->setTitle(pht('Manage Home Menu'))
->setCrumbs($crumbs)
->appendChild($view);
}
}

View file

@ -0,0 +1,29 @@
<?php
final class PhabricatorHomeMenuItemController
extends PhabricatorHomeController {
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$type = $request->getURIData('type');
$custom_phid = null;
if ($type == 'personal') {
$custom_phid = $viewer->getPHID();
}
$application = 'PhabricatorHomeApplication';
$home_app = id(new PhabricatorApplicationQuery())
->setViewer($viewer)
->withClasses(array($application))
->withInstalled(true)
->executeOne();
$engine = id(new PhabricatorHomeProfileMenuEngine())
->setProfileObject($home_app)
->setCustomPHID($custom_phid)
->setController($this);
return $engine->buildResponse();
}
}

View file

@ -0,0 +1,58 @@
<?php
final class PhabricatorHomeProfileMenuEngine
extends PhabricatorProfileMenuEngine {
protected function isMenuEngineConfigurable() {
return true;
}
protected function getItemURI($path) {
$object = $this->getProfileObject();
$custom = $this->getCustomPHID();
if ($custom) {
return "/home/menu/personal/item/{$path}";
} else {
return "/home/menu/global/item/{$path}";
}
}
protected function getBuiltinProfileItems($object) {
$viewer = $this->getViewer();
$items = array();
$custom_phid = $this->getCustomPHID();
$applications = id(new PhabricatorApplicationQuery())
->setViewer($viewer)
->withInstalled(true)
->withUnlisted(false)
->withLaunchable(true)
->execute();
foreach ($applications as $application) {
if (!$application->isPinnedByDefault($viewer)) {
continue;
}
$properties = array(
'name' => $application->getName(),
'application' => $application->getPHID(),
);
$items[] = $this->newItem()
->setBuiltinKey($application->getPHID())
->setMenuItemKey(PhabricatorApplicationProfileMenuItem::MENUITEMKEY)
->setMenuItemProperties($properties);
}
// Single Manage Item, switches URI based on admin/user
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorHomeConstants::ITEM_MANAGE)
->setMenuItemKey(
PhabricatorHomeManageProfileMenuItem::MENUITEMKEY);
return $items;
}
}

View file

@ -0,0 +1,72 @@
<?php
final class PhabricatorHomeManageProfileMenuItem
extends PhabricatorProfileMenuItem {
const MENUITEMKEY = 'home.manage.menu';
public function getMenuItemTypeName() {
return pht('Manage Home Menu');
}
private function getDefaultName() {
return pht('Manage');
}
public function canHideMenuItem(
PhabricatorProfileMenuItemConfiguration $config) {
return false;
}
public function canMakeDefault(
PhabricatorProfileMenuItemConfiguration $config) {
return false;
}
public function getDisplayName(
PhabricatorProfileMenuItemConfiguration $config) {
$name = $config->getMenuItemProperty('name');
if (strlen($name)) {
return $name;
}
return $this->getDefaultName();
}
public function buildEditEngineFields(
PhabricatorProfileMenuItemConfiguration $config) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setPlaceholder($this->getDefaultName())
->setValue($config->getMenuItemProperty('name')),
);
}
protected function newNavigationMenuItems(
PhabricatorProfileMenuItemConfiguration $config) {
$viewer = $this->getViewer();
if ($viewer->isLoggedIn()) {
$admin = $viewer->getIsAdmin();
$name = $this->getDisplayName($config);
$icon = 'fa-pencil';
$href = '/home/menu/personal/item/configure/';
if ($admin) {
$href = '/home/menu/';
}
$item = $this->newItem()
->setHref($href)
->setName($name)
->setIcon($icon);
}
return array(
$item,
);
}
}

View file

@ -11,6 +11,16 @@ final class ManiphestCreateTaskConduitAPIMethod
return pht('Create a new Maniphest task.');
}
public function getMethodStatus() {
return self::METHOD_STATUS_FROZEN;
}
public function getMethodStatusDescription() {
return pht(
'This method is frozen and will eventually be deprecated. New code '.
'should use "maniphest.edit" instead.');
}
protected function defineParamTypes() {
return $this->getTaskFields($is_new = true);
}

View file

@ -10,6 +10,16 @@ final class ManiphestInfoConduitAPIMethod extends ManiphestConduitAPIMethod {
return pht('Retrieve information about a Maniphest task, given its ID.');
}
public function getMethodStatus() {
return self::METHOD_STATUS_FROZEN;
}
public function getMethodStatusDescription() {
return pht(
'This method is frozen and will eventually be deprecated. New code '.
'should use "maniphest.search" instead.');
}
protected function defineParamTypes() {
return array(
'task_id' => 'required id',

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