Page MenuHomePhorge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index a56b3c3a3d..cb5645fc94 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1,1655 +1,1657 @@
<?php
/**
* This file is automatically generated. Use 'phutil_mapper.php' to rebuild it.
* @generated
*/
phutil_register_library_map(array(
'class' =>
array(
'Aphront304Response' => 'aphront/response/304',
'Aphront400Response' => 'aphront/response/400',
'Aphront403Response' => 'aphront/response/403',
'Aphront404Response' => 'aphront/response/404',
'AphrontAjaxResponse' => 'aphront/response/ajax',
'AphrontApplicationConfiguration' => 'aphront/applicationconfiguration',
'AphrontAttachedFileView' => 'view/control/attachedfile',
'AphrontCSRFException' => 'aphront/exception/csrf',
'AphrontCalendarMonthView' => 'applications/calendar/view/month',
'AphrontContextBarView' => 'view/layout/contextbar',
'AphrontController' => 'aphront/controller',
'AphrontCrumbsView' => 'view/layout/crumbs',
'AphrontDatabaseConnection' => 'storage/connection/base',
'AphrontDatabaseTransactionState' => 'storage/transaction',
'AphrontDefaultApplicationConfiguration' => 'aphront/default/configuration',
'AphrontDialogResponse' => 'aphront/response/dialog',
'AphrontDialogView' => 'view/dialog',
'AphrontErrorView' => 'view/form/error',
'AphrontException' => 'aphront/exception/base',
'AphrontFilePreviewView' => 'view/layout/filepreview',
'AphrontFileResponse' => 'aphront/response/file',
'AphrontFormCheckboxControl' => 'view/form/control/checkbox',
'AphrontFormControl' => 'view/form/control/base',
'AphrontFormDividerControl' => 'view/form/control/divider',
'AphrontFormDragAndDropUploadControl' => 'view/form/control/draganddropupload',
'AphrontFormFileControl' => 'view/form/control/file',
'AphrontFormInsetView' => 'view/form/inset',
'AphrontFormLayoutView' => 'view/form/layout',
'AphrontFormMarkupControl' => 'view/form/control/markup',
'AphrontFormPasswordControl' => 'view/form/control/password',
'AphrontFormRadioButtonControl' => 'view/form/control/radio',
'AphrontFormRecaptchaControl' => 'view/form/control/recaptcha',
'AphrontFormSelectControl' => 'view/form/control/select',
'AphrontFormStaticControl' => 'view/form/control/static',
'AphrontFormSubmitControl' => 'view/form/control/submit',
'AphrontFormTextAreaControl' => 'view/form/control/textarea',
'AphrontFormTextControl' => 'view/form/control/text',
'AphrontFormToggleButtonsControl' => 'view/form/control/togglebuttons',
'AphrontFormTokenizerControl' => 'view/form/control/tokenizer',
'AphrontFormView' => 'view/form/base',
'AphrontHTTPSink' => 'aphront/sink/base',
'AphrontHTTPSinkTestCase' => 'aphront/sink/base/__tests__',
'AphrontHeadsupActionListView' => 'view/layout/headsup/actionlist',
'AphrontHeadsupActionView' => 'view/layout/headsup/action',
'AphrontIsolatedDatabaseConnection' => 'storage/connection/isolated',
'AphrontIsolatedDatabaseConnectionTestCase' => 'storage/connection/isolated/__tests__',
'AphrontIsolatedHTTPSink' => 'aphront/sink/test',
'AphrontJSONResponse' => 'aphront/response/json',
'AphrontJavelinView' => 'view/javelin-view',
'AphrontKeyboardShortcutsAvailableView' => 'view/widget/keyboardshortcuts',
'AphrontListFilterView' => 'view/layout/listfilter',
'AphrontMiniPanelView' => 'view/layout/minipanel',
'AphrontMySQLDatabaseConnection' => 'storage/connection/mysql',
'AphrontMySQLDatabaseConnectionTestCase' => 'storage/connection/mysql/__tests__',
'AphrontNullView' => 'view/null',
'AphrontPHPHTTPSink' => 'aphront/sink/php',
'AphrontPageView' => 'view/page/base',
'AphrontPagerView' => 'view/control/pager',
'AphrontPanelView' => 'view/layout/panel',
'AphrontPlainTextResponse' => 'aphront/response/plaintext',
'AphrontProxyResponse' => 'aphront/response/proxy',
'AphrontQueryAccessDeniedException' => 'storage/exception/accessdenied',
'AphrontQueryConnectionException' => 'storage/exception/connection',
'AphrontQueryConnectionLostException' => 'storage/exception/connectionlost',
'AphrontQueryCountException' => 'storage/exception/count',
'AphrontQueryDuplicateKeyException' => 'storage/exception/duplicatekey',
'AphrontQueryException' => 'storage/exception/base',
'AphrontQueryObjectMissingException' => 'storage/exception/objectmissing',
'AphrontQueryParameterException' => 'storage/exception/parameter',
'AphrontQueryRecoverableException' => 'storage/exception/recoverable',
'AphrontQuerySchemaException' => 'storage/exception/schema',
'AphrontRedirectException' => 'aphront/exception/redirect',
'AphrontRedirectResponse' => 'aphront/response/redirect',
'AphrontReloadResponse' => 'aphront/response/reload',
'AphrontRequest' => 'aphront/request',
'AphrontRequestFailureView' => 'view/page/failure',
'AphrontRequestTestCase' => 'aphront/request/__tests__',
'AphrontResponse' => 'aphront/response/base',
'AphrontScopedUnguardedWriteCapability' => 'aphront/writeguard/scopeguard',
'AphrontSideNavFilterView' => 'view/layout/sidenavfilter',
'AphrontSideNavView' => 'view/layout/sidenav',
'AphrontTableView' => 'view/control/table',
'AphrontTokenizerTemplateView' => 'view/control/tokenizer',
'AphrontTypeaheadTemplateView' => 'view/control/typeahead',
'AphrontURIMapper' => 'aphront/mapper',
'AphrontView' => 'view/base',
'AphrontWebpageResponse' => 'aphront/response/webpage',
'AphrontWriteGuard' => 'aphront/writeguard',
'CelerityAPI' => 'infrastructure/celerity/api',
'CelerityResourceController' => 'infrastructure/celerity/controller',
'CelerityResourceGraph' => 'infrastructure/celerity/graph',
'CelerityResourceMap' => 'infrastructure/celerity/map',
'CelerityStaticResourceResponse' => 'infrastructure/celerity/response',
'ConduitAPIMethod' => 'applications/conduit/method/base',
'ConduitAPIRequest' => 'applications/conduit/protocol/request',
'ConduitAPIResponse' => 'applications/conduit/protocol/response',
'ConduitAPI_arcanist_Method' => 'applications/conduit/method/arcanist/base',
'ConduitAPI_arcanist_projectinfo_Method' => 'applications/conduit/method/arcanist/projectinfo',
'ConduitAPI_audit_Method' => 'applications/conduit/method/audit/base',
'ConduitAPI_audit_query_Method' => 'applications/conduit/method/audit/query',
'ConduitAPI_chatlog_Method' => 'applications/conduit/method/chatlog/base',
'ConduitAPI_chatlog_query_Method' => 'applications/conduit/method/chatlog/query',
'ConduitAPI_chatlog_record_Method' => 'applications/conduit/method/chatlog/record',
'ConduitAPI_conduit_connect_Method' => 'applications/conduit/method/conduit/connect',
'ConduitAPI_conduit_getcertificate_Method' => 'applications/conduit/method/conduit/getcertificate',
'ConduitAPI_conduit_ping_Method' => 'applications/conduit/method/conduit/ping',
'ConduitAPI_daemon_launched_Method' => 'applications/conduit/method/daemon/launched',
'ConduitAPI_daemon_log_Method' => 'applications/conduit/method/daemon/log',
'ConduitAPI_differential_createcomment_Method' => 'applications/conduit/method/differential/createcomment',
'ConduitAPI_differential_creatediff_Method' => 'applications/conduit/method/differential/creatediff',
'ConduitAPI_differential_createrevision_Method' => 'applications/conduit/method/differential/createrevision',
'ConduitAPI_differential_find_Method' => 'applications/conduit/method/differential/find',
'ConduitAPI_differential_getalldiffs_Method' => 'applications/conduit/method/differential/getalldiffs',
'ConduitAPI_differential_getcommitmessage_Method' => 'applications/conduit/method/differential/getcommitmessage',
'ConduitAPI_differential_getcommitpaths_Method' => 'applications/conduit/method/differential/getcommitpaths',
'ConduitAPI_differential_getdiff_Method' => 'applications/conduit/method/differential/getdiff',
'ConduitAPI_differential_getrevision_Method' => 'applications/conduit/method/differential/getrevision',
'ConduitAPI_differential_getrevisioncomments_Method' => 'applications/conduit/method/differential/getrevisioncomments',
'ConduitAPI_differential_getrevisionfeedback_Method' => 'applications/conduit/method/differential/getrevisionfeedback',
'ConduitAPI_differential_markcommitted_Method' => 'applications/conduit/method/differential/markcommitted',
'ConduitAPI_differential_parsecommitmessage_Method' => 'applications/conduit/method/differential/parsecommitmessage',
'ConduitAPI_differential_query_Method' => 'applications/conduit/method/differential/query',
'ConduitAPI_differential_setdiffproperty_Method' => 'applications/conduit/method/differential/setdiffproperty',
'ConduitAPI_differential_updaterevision_Method' => 'applications/conduit/method/differential/updaterevision',
'ConduitAPI_differential_updatetaskrevisionassoc_Method' => 'applications/conduit/method/differential/updatetaskrevisionassoc',
'ConduitAPI_differential_updateunitresults_Method' => 'applications/conduit/method/differential/updateunitresults',
'ConduitAPI_diffusion_findsymbols_Method' => 'applications/conduit/method/diffusion/findsymbols',
'ConduitAPI_diffusion_getcommits_Method' => 'applications/conduit/method/diffusion/getcommits',
'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'applications/conduit/method/diffusion/getrecentcommitsbypath',
'ConduitAPI_feed_publish_Method' => 'applications/conduit/method/feed/publish',
'ConduitAPI_feed_query_Method' => 'applications/conduit/method/feed/query',
'ConduitAPI_file_download_Method' => 'applications/conduit/method/file/download',
'ConduitAPI_file_info_Method' => 'applications/conduit/method/file/info',
'ConduitAPI_file_upload_Method' => 'applications/conduit/method/file/upload',
'ConduitAPI_macro_Method' => 'applications/conduit/method/macro/base',
'ConduitAPI_macro_query_Method' => 'applications/conduit/method/macro/query',
'ConduitAPI_maniphest_Method' => 'applications/conduit/method/maniphest/base',
'ConduitAPI_maniphest_createtask_Method' => 'applications/conduit/method/maniphest/createtask',
'ConduitAPI_maniphest_find_Method' => 'applications/conduit/method/maniphest/find',
'ConduitAPI_maniphest_gettasktransactions_Method' => 'applications/conduit/method/maniphest/gettasktransactions',
'ConduitAPI_maniphest_info_Method' => 'applications/conduit/method/maniphest/info',
'ConduitAPI_maniphest_update_Method' => 'applications/conduit/method/maniphest/update',
'ConduitAPI_paste_Method' => 'applications/conduit/method/paste/base',
'ConduitAPI_paste_create_Method' => 'applications/conduit/method/paste/create',
'ConduitAPI_paste_info_Method' => 'applications/conduit/method/paste/info',
'ConduitAPI_path_getowners_Method' => 'applications/conduit/method/path/getowners',
'ConduitAPI_phid_Method' => 'applications/conduit/method/phid/base',
'ConduitAPI_phid_info_Method' => 'applications/conduit/method/phid/info',
'ConduitAPI_phid_query_Method' => 'applications/conduit/method/phid/query',
'ConduitAPI_phriction_Method' => 'applications/conduit/method/phriction/base',
'ConduitAPI_phriction_edit_Method' => 'applications/conduit/method/phriction/edit',
'ConduitAPI_phriction_history_Method' => 'applications/conduit/method/phriction/history',
'ConduitAPI_phriction_info_Method' => 'applications/conduit/method/phriction/info',
'ConduitAPI_project_Method' => 'applications/conduit/method/project/base',
'ConduitAPI_project_query_Method' => 'applications/conduit/method/project/query',
'ConduitAPI_remarkup_process_Method' => 'applications/conduit/method/remarkup/process',
'ConduitAPI_slowvote_info_Method' => 'applications/conduit/method/slowvote/info',
'ConduitAPI_user_Method' => 'applications/conduit/method/user/base',
'ConduitAPI_user_find_Method' => 'applications/conduit/method/user/find',
'ConduitAPI_user_info_Method' => 'applications/conduit/method/user/info',
'ConduitAPI_user_whoami_Method' => 'applications/conduit/method/user/whoami',
'ConduitException' => 'applications/conduit/protocol/exception',
'DarkConsoleConfigPlugin' => 'aphront/console/plugin/config',
'DarkConsoleController' => 'aphront/console/controller',
'DarkConsoleCore' => 'aphront/console/core',
'DarkConsoleErrorLogPlugin' => 'aphront/console/plugin/errorlog',
'DarkConsoleErrorLogPluginAPI' => 'aphront/console/plugin/errorlog/api',
'DarkConsoleEventPlugin' => 'aphront/console/plugin/event',
'DarkConsoleEventPluginAPI' => 'aphront/console/plugin/event/api',
'DarkConsolePlugin' => 'aphront/console/plugin/base',
'DarkConsoleRequestPlugin' => 'aphront/console/plugin/request',
'DarkConsoleServicesPlugin' => 'aphront/console/plugin/services',
'DarkConsoleXHProfPlugin' => 'aphront/console/plugin/xhprof',
'DarkConsoleXHProfPluginAPI' => 'aphront/console/plugin/xhprof/api',
'DatabaseConfigurationProvider' => 'applications/base/storage/configuration',
'DifferentialAction' => 'applications/differential/constants/action',
'DifferentialActionHasNoEffectException' => 'applications/differential/exception/noeffect',
'DifferentialAddCommentView' => 'applications/differential/view/addcomment',
'DifferentialAffectedPath' => 'applications/differential/storage/affectedpath',
'DifferentialApplyPatchFieldSpecification' => 'applications/differential/field/specification/applypatch',
'DifferentialArcanistProjectFieldSpecification' => 'applications/differential/field/specification/arcanistproject',
'DifferentialAuditorsFieldSpecification' => 'applications/differential/field/specification/auditors',
'DifferentialAuthorFieldSpecification' => 'applications/differential/field/specification/author',
'DifferentialAuxiliaryField' => 'applications/differential/storage/auxiliaryfield',
'DifferentialBlameRevisionFieldSpecification' => 'applications/differential/field/specification/blamerev',
'DifferentialBranchFieldSpecification' => 'applications/differential/field/specification/branch',
'DifferentialCCWelcomeMail' => 'applications/differential/mail/ccwelcome',
'DifferentialCCsFieldSpecification' => 'applications/differential/field/specification/ccs',
'DifferentialChangeType' => 'applications/differential/constants/changetype',
'DifferentialChangeset' => 'applications/differential/storage/changeset',
'DifferentialChangesetDetailView' => 'applications/differential/view/changesetdetailview',
'DifferentialChangesetListView' => 'applications/differential/view/changesetlistview',
'DifferentialChangesetParser' => 'applications/differential/parser/changeset',
'DifferentialChangesetViewController' => 'applications/differential/controller/changesetview',
'DifferentialComment' => 'applications/differential/storage/comment',
'DifferentialCommentEditor' => 'applications/differential/editor/comment',
'DifferentialCommentMail' => 'applications/differential/mail/comment',
'DifferentialCommentPreviewController' => 'applications/differential/controller/commentpreview',
'DifferentialCommentSaveController' => 'applications/differential/controller/commentsave',
'DifferentialCommitsFieldSpecification' => 'applications/differential/field/specification/commits',
'DifferentialController' => 'applications/differential/controller/base',
'DifferentialDAO' => 'applications/differential/storage/base',
'DifferentialDateCreatedFieldSpecification' => 'applications/differential/field/specification/datecreated',
'DifferentialDateModifiedFieldSpecification' => 'applications/differential/field/specification/datemodified',
'DifferentialDefaultFieldSelector' => 'applications/differential/field/selector/default',
'DifferentialDependenciesFieldSpecification' => 'applications/differential/field/specification/dependencies',
'DifferentialDiff' => 'applications/differential/storage/diff',
'DifferentialDiffContentMail' => 'applications/differential/mail/diffcontent',
'DifferentialDiffCreateController' => 'applications/differential/controller/diffcreate',
'DifferentialDiffProperty' => 'applications/differential/storage/diffproperty',
'DifferentialDiffTableOfContentsView' => 'applications/differential/view/difftableofcontents',
'DifferentialDiffViewController' => 'applications/differential/controller/diffview',
'DifferentialException' => 'applications/differential/exception/base',
'DifferentialExceptionMail' => 'applications/differential/mail/exception',
'DifferentialExportPatchFieldSpecification' => 'applications/differential/field/specification/exportpatch',
'DifferentialFieldDataNotAvailableException' => 'applications/differential/field/exception/notavailable',
'DifferentialFieldParseException' => 'applications/differential/field/exception/parse',
'DifferentialFieldSelector' => 'applications/differential/field/selector/base',
'DifferentialFieldSpecification' => 'applications/differential/field/specification/base',
'DifferentialFieldSpecificationIncompleteException' => 'applications/differential/field/exception/incomplete',
'DifferentialFieldValidationException' => 'applications/differential/field/exception/validation',
'DifferentialGitSVNIDFieldSpecification' => 'applications/differential/field/specification/gitsvnid',
'DifferentialHostFieldSpecification' => 'applications/differential/field/specification/host',
'DifferentialHunk' => 'applications/differential/storage/hunk',
'DifferentialInlineComment' => 'applications/differential/storage/inlinecomment',
'DifferentialInlineCommentEditController' => 'applications/differential/controller/inlinecommentedit',
'DifferentialInlineCommentEditView' => 'applications/differential/view/inlinecommentedit',
'DifferentialInlineCommentPreviewController' => 'applications/differential/controller/inlinecommentpreview',
'DifferentialInlineCommentView' => 'applications/differential/view/inlinecomment',
'DifferentialLinesFieldSpecification' => 'applications/differential/field/specification/lines',
'DifferentialLintFieldSpecification' => 'applications/differential/field/specification/lint',
'DifferentialLintStatus' => 'applications/differential/constants/lintstatus',
'DifferentialLocalCommitsView' => 'applications/differential/view/localcommits',
'DifferentialMail' => 'applications/differential/mail/base',
'DifferentialManiphestTasksFieldSpecification' => 'applications/differential/field/specification/maniphesttasks',
'DifferentialNewDiffMail' => 'applications/differential/mail/newdiff',
'DifferentialPathFieldSpecification' => 'applications/differential/field/specification/path',
'DifferentialPrimaryPaneView' => 'applications/differential/view/primarypane',
'DifferentialReplyHandler' => 'applications/differential/replyhandler',
'DifferentialRevertPlanFieldSpecification' => 'applications/differential/field/specification/revertplan',
'DifferentialReviewRequestMail' => 'applications/differential/mail/reviewrequest',
'DifferentialReviewedByFieldSpecification' => 'applications/differential/field/specification/reviewedby',
'DifferentialReviewersFieldSpecification' => 'applications/differential/field/specification/reviewers',
'DifferentialRevision' => 'applications/differential/storage/revision',
'DifferentialRevisionCommentListView' => 'applications/differential/view/revisioncommentlist',
'DifferentialRevisionCommentView' => 'applications/differential/view/revisioncomment',
'DifferentialRevisionControlSystem' => 'applications/differential/constants/revisioncontrolsystem',
'DifferentialRevisionDetailRenderer' => 'applications/differential/controller/customrenderer',
'DifferentialRevisionDetailView' => 'applications/differential/view/revisiondetail',
'DifferentialRevisionEditController' => 'applications/differential/controller/revisionedit',
'DifferentialRevisionEditor' => 'applications/differential/editor/revision',
'DifferentialRevisionIDFieldParserTestCase' => 'applications/differential/field/specification/revisionid/__tests__',
'DifferentialRevisionIDFieldSpecification' => 'applications/differential/field/specification/revisionid',
'DifferentialRevisionListController' => 'applications/differential/controller/revisionlist',
'DifferentialRevisionListData' => 'applications/differential/data/revisionlist',
'DifferentialRevisionListView' => 'applications/differential/view/revisionlist',
'DifferentialRevisionQuery' => 'applications/differential/query/revision',
'DifferentialRevisionStatsController' => 'applications/differential/controller/revisionstats',
'DifferentialRevisionStatsView' => 'applications/differential/view/revisionstats',
'DifferentialRevisionStatusFieldSpecification' => 'applications/differential/field/specification/revisionstatus',
'DifferentialRevisionUpdateHistoryView' => 'applications/differential/view/revisionupdatehistory',
'DifferentialRevisionViewController' => 'applications/differential/controller/revisionview',
'DifferentialSubscribeController' => 'applications/differential/controller/subscribe',
'DifferentialSummaryFieldSpecification' => 'applications/differential/field/specification/summary',
'DifferentialTasksAttacher' => 'applications/differential/tasks',
'DifferentialTestPlanFieldSpecification' => 'applications/differential/field/specification/testplan',
'DifferentialTitleFieldSpecification' => 'applications/differential/field/specification/title',
'DifferentialUnitFieldSpecification' => 'applications/differential/field/specification/unit',
'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus',
'DifferentialUnitTestResult' => 'applications/differential/constants/unittestresult',
'DiffusionBranchInformation' => 'applications/diffusion/data/branch',
'DiffusionBranchQuery' => 'applications/diffusion/query/branch/base',
'DiffusionBranchTableView' => 'applications/diffusion/view/branchtable',
'DiffusionBrowseController' => 'applications/diffusion/controller/browse',
'DiffusionBrowseFileController' => 'applications/diffusion/controller/file',
'DiffusionBrowseQuery' => 'applications/diffusion/query/browse/base',
'DiffusionBrowseTableView' => 'applications/diffusion/view/browsetable',
'DiffusionChangeController' => 'applications/diffusion/controller/change',
'DiffusionCommentListView' => 'applications/diffusion/view/commentlist',
'DiffusionCommentView' => 'applications/diffusion/view/comment',
'DiffusionCommitChangeTableView' => 'applications/diffusion/view/commitchangetable',
'DiffusionCommitController' => 'applications/diffusion/controller/commit',
'DiffusionContainsQuery' => 'applications/diffusion/query/contains/base',
'DiffusionController' => 'applications/diffusion/controller/base',
'DiffusionDiffController' => 'applications/diffusion/controller/diff',
'DiffusionDiffQuery' => 'applications/diffusion/query/diff/base',
'DiffusionEmptyResultView' => 'applications/diffusion/view/emptyresult',
'DiffusionFileContent' => 'applications/diffusion/data/filecontent',
'DiffusionFileContentQuery' => 'applications/diffusion/query/filecontent/base',
'DiffusionGitBranchQuery' => 'applications/diffusion/query/branch/git',
'DiffusionGitBranchQueryTestCase' => 'applications/diffusion/query/branch/git/__tests__',
'DiffusionGitBrowseQuery' => 'applications/diffusion/query/browse/git',
'DiffusionGitContainsQuery' => 'applications/diffusion/query/contains/git',
'DiffusionGitDiffQuery' => 'applications/diffusion/query/diff/git',
'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/git',
'DiffusionGitHistoryQuery' => 'applications/diffusion/query/history/git',
'DiffusionGitLastModifiedQuery' => 'applications/diffusion/query/lastmodified/git',
'DiffusionGitRequest' => 'applications/diffusion/request/git',
'DiffusionHistoryController' => 'applications/diffusion/controller/history',
'DiffusionHistoryQuery' => 'applications/diffusion/query/history/base',
'DiffusionHistoryTableView' => 'applications/diffusion/view/historytable',
'DiffusionHomeController' => 'applications/diffusion/controller/home',
'DiffusionInlineCommentController' => 'applications/diffusion/controller/inline',
'DiffusionLastModifiedController' => 'applications/diffusion/controller/lastmodified',
'DiffusionLastModifiedQuery' => 'applications/diffusion/query/lastmodified/base',
'DiffusionMercurialBranchQuery' => 'applications/diffusion/query/branch/mercurial',
'DiffusionMercurialBrowseQuery' => 'applications/diffusion/query/browse/mercurial',
'DiffusionMercurialContainsQuery' => 'applications/diffusion/query/contains/mercurial',
'DiffusionMercurialDiffQuery' => 'applications/diffusion/query/diff/mercurial',
'DiffusionMercurialFileContentQuery' => 'applications/diffusion/query/filecontent/mercurial',
'DiffusionMercurialHistoryQuery' => 'applications/diffusion/query/history/mercurial',
'DiffusionMercurialLastModifiedQuery' => 'applications/diffusion/query/lastmodified/mercurial',
'DiffusionMercurialRequest' => 'applications/diffusion/request/mercurial',
'DiffusionPathChange' => 'applications/diffusion/data/pathchange',
'DiffusionPathChangeQuery' => 'applications/diffusion/query/pathchange/base',
'DiffusionPathCompleteController' => 'applications/diffusion/controller/pathcomplete',
'DiffusionPathIDQuery' => 'applications/diffusion/query/pathid/base',
'DiffusionPathQueryTestCase' => 'applications/diffusion/query/pathid/base/__tests__',
'DiffusionPathValidateController' => 'applications/diffusion/controller/pathvalidate',
'DiffusionQuery' => 'applications/diffusion/query/base',
'DiffusionRepositoryController' => 'applications/diffusion/controller/repository',
'DiffusionRepositoryPath' => 'applications/diffusion/data/repositorypath',
'DiffusionRequest' => 'applications/diffusion/request/base',
'DiffusionSVNContainsQuery' => 'applications/diffusion/query/contains/svn',
'DiffusionSvnBrowseQuery' => 'applications/diffusion/query/browse/svn',
'DiffusionSvnDiffQuery' => 'applications/diffusion/query/diff/svn',
'DiffusionSvnFileContentQuery' => 'applications/diffusion/query/filecontent/svn',
'DiffusionSvnHistoryQuery' => 'applications/diffusion/query/history/svn',
'DiffusionSvnLastModifiedQuery' => 'applications/diffusion/query/lastmodified/svn',
'DiffusionSvnRequest' => 'applications/diffusion/request/svn',
'DiffusionSymbolController' => 'applications/diffusion/controller/symbol',
'DiffusionSymbolQuery' => 'applications/diffusion/query/symbol',
+ 'DiffusionURITestCase' => 'applications/diffusion/request/base/__tests__',
'DiffusionView' => 'applications/diffusion/view/base',
'DrydockAllocator' => 'applications/drydock/allocator/resource',
'DrydockAllocatorWorker' => 'applications/drydock/allocator/worker',
'DrydockBlueprint' => 'applications/drydock/blueprint/base',
'DrydockCommandInterface' => 'applications/drydock/interface/command/base',
'DrydockConstants' => 'applications/drydock/constants/base',
'DrydockController' => 'applications/drydock/controller/base',
'DrydockDAO' => 'applications/drydock/storage/base',
'DrydockEC2HostBlueprint' => 'applications/drydock/blueprint/ec2host',
'DrydockInterface' => 'applications/drydock/interface/base',
'DrydockLease' => 'applications/drydock/storage/lease',
'DrydockLeaseListController' => 'applications/drydock/controller/leaselist',
'DrydockLeaseStatus' => 'applications/drydock/constants/leasestatus',
'DrydockLocalCommandInterface' => 'applications/drydock/interface/command/local',
'DrydockLocalHostBlueprint' => 'applications/drydock/blueprint/localhost',
'DrydockRemoteHostBlueprint' => 'applications/drydock/blueprint/remotehost',
'DrydockResource' => 'applications/drydock/storage/resource',
'DrydockResourceAllocateController' => 'applications/drydock/controller/resourceallocate',
'DrydockResourceListController' => 'applications/drydock/controller/resourcelist',
'DrydockResourceStatus' => 'applications/drydock/constants/resourcestatus',
'DrydockSSHCommandInterface' => 'applications/drydock/interface/command/ssh',
'HeraldAction' => 'applications/herald/storage/action',
'HeraldActionConfig' => 'applications/herald/config/action',
'HeraldAllRulesController' => 'applications/herald/controller/all',
'HeraldApplyTranscript' => 'applications/herald/storage/transcript/apply',
'HeraldCommitAdapter' => 'applications/herald/adapter/commit',
'HeraldCondition' => 'applications/herald/storage/condition',
'HeraldConditionConfig' => 'applications/herald/config/condition',
'HeraldConditionTranscript' => 'applications/herald/storage/transcript/condition',
'HeraldContentTypeConfig' => 'applications/herald/config/contenttype',
'HeraldController' => 'applications/herald/controller/base',
'HeraldDAO' => 'applications/herald/storage/base',
'HeraldDeleteController' => 'applications/herald/controller/delete',
'HeraldDifferentialRevisionAdapter' => 'applications/herald/adapter/differential',
'HeraldDryRunAdapter' => 'applications/herald/adapter/dryrun',
'HeraldEffect' => 'applications/herald/engine/effect',
'HeraldEngine' => 'applications/herald/engine/engine',
'HeraldFieldConfig' => 'applications/herald/config/field',
'HeraldHomeController' => 'applications/herald/controller/home',
'HeraldInvalidConditionException' => 'applications/herald/engine/engine/exception',
'HeraldInvalidFieldException' => 'applications/herald/engine/engine/exception',
'HeraldNewController' => 'applications/herald/controller/new',
'HeraldObjectAdapter' => 'applications/herald/adapter/base',
'HeraldObjectTranscript' => 'applications/herald/storage/transcript/object',
'HeraldRecursiveConditionsException' => 'applications/herald/engine/engine/exception',
'HeraldRepetitionPolicyConfig' => 'applications/herald/config/repetitionpolicy',
'HeraldRule' => 'applications/herald/storage/rule',
'HeraldRuleController' => 'applications/herald/controller/rule',
'HeraldRuleEdit' => 'applications/herald/storage/edithistory',
'HeraldRuleEditHistoryController' => 'applications/herald/controller/edithistory',
'HeraldRuleEditHistoryView' => 'applications/herald/view/edithistory',
'HeraldRuleListView' => 'applications/herald/view/rulelist',
'HeraldRuleTranscript' => 'applications/herald/storage/transcript/rule',
'HeraldRuleTypeConfig' => 'applications/herald/config/ruletype',
'HeraldTestConsoleController' => 'applications/herald/controller/test',
'HeraldTranscript' => 'applications/herald/storage/transcript/base',
'HeraldTranscriptController' => 'applications/herald/controller/transcript',
'HeraldTranscriptListController' => 'applications/herald/controller/transcriptlist',
'HeraldValueTypeConfig' => 'applications/herald/config/valuetype',
'Javelin' => 'infrastructure/javelin/api',
'JavelinReactorExample' => 'applications/uiexample/examples/reactor',
'JavelinViewExample' => 'applications/uiexample/examples/client',
'JavelinViewExampleServerView' => 'applications/uiexample/examples/client',
'LiskDAO' => 'storage/lisk/dao',
'LiskEphemeralObjectException' => 'storage/lisk/dao',
'LiskIsolationTestCase' => 'storage/lisk/dao/__tests__',
'LiskIsolationTestDAO' => 'storage/lisk/dao/__tests__',
'LiskIsolationTestDAOException' => 'storage/lisk/dao/__tests__',
'ManiphestAction' => 'applications/maniphest/constants/action',
'ManiphestAuxiliaryFieldDefaultSpecification' => 'applications/maniphest/auxiliaryfield/default',
'ManiphestAuxiliaryFieldSpecification' => 'applications/maniphest/auxiliaryfield/base',
'ManiphestAuxiliaryFieldTypeException' => 'applications/maniphest/auxiliaryfield/typeexception',
'ManiphestAuxiliaryFieldValidationException' => 'applications/maniphest/auxiliaryfield/validationexception',
'ManiphestBatchEditController' => 'applications/maniphest/controller/batch',
'ManiphestConstants' => 'applications/maniphest/constants/base',
'ManiphestController' => 'applications/maniphest/controller/base',
'ManiphestDAO' => 'applications/maniphest/storage/base',
'ManiphestDefaultTaskExtensions' => 'applications/maniphest/extensions/task',
'ManiphestExportController' => 'applications/maniphest/controller/export',
'ManiphestReplyHandler' => 'applications/maniphest/replyhandler',
'ManiphestReportController' => 'applications/maniphest/controller/report',
'ManiphestTask' => 'applications/maniphest/storage/task',
'ManiphestTaskAuxiliaryStorage' => 'applications/maniphest/storage/auxiliary',
'ManiphestTaskDescriptionChangeController' => 'applications/maniphest/controller/descriptionchange',
'ManiphestTaskDescriptionPreviewController' => 'applications/maniphest/controller/descriptionpreview',
'ManiphestTaskDetailController' => 'applications/maniphest/controller/taskdetail',
'ManiphestTaskEditController' => 'applications/maniphest/controller/taskedit',
'ManiphestTaskExtensions' => 'applications/maniphest/extensions/base',
'ManiphestTaskListController' => 'applications/maniphest/controller/tasklist',
'ManiphestTaskListView' => 'applications/maniphest/view/tasklist',
'ManiphestTaskOwner' => 'applications/maniphest/constants/owner',
'ManiphestTaskPriority' => 'applications/maniphest/constants/priority',
'ManiphestTaskProject' => 'applications/maniphest/storage/taskproject',
'ManiphestTaskQuery' => 'applications/maniphest/query',
'ManiphestTaskStatus' => 'applications/maniphest/constants/status',
'ManiphestTaskSubscriber' => 'applications/maniphest/storage/subscriber',
'ManiphestTaskSummaryView' => 'applications/maniphest/view/tasksummary',
'ManiphestTransaction' => 'applications/maniphest/storage/transaction',
'ManiphestTransactionDetailView' => 'applications/maniphest/view/transactiondetail',
'ManiphestTransactionEditor' => 'applications/maniphest/editor/transaction',
'ManiphestTransactionListView' => 'applications/maniphest/view/transactionlist',
'ManiphestTransactionPreviewController' => 'applications/maniphest/controller/transactionpreview',
'ManiphestTransactionSaveController' => 'applications/maniphest/controller/transactionsave',
'ManiphestTransactionType' => 'applications/maniphest/constants/transactiontype',
'ManiphestView' => 'applications/maniphest/view/base',
'MetaMTAConstants' => 'applications/metamta/constants/base',
'MetaMTANotificationType' => 'applications/metamta/constants/notificationtype',
'Phabricator404Controller' => 'applications/base/controller/404',
'PhabricatorAphlictTestPageController' => 'applications/notifications/controller/test',
'PhabricatorAuditActionConstants' => 'applications/audit/constants/action',
'PhabricatorAuditAddCommentController' => 'applications/audit/controller/addcomment',
'PhabricatorAuditComment' => 'applications/audit/storage/auditcomment',
'PhabricatorAuditCommentEditor' => 'applications/audit/editor/comment',
'PhabricatorAuditCommitListView' => 'applications/audit/view/commitlist',
'PhabricatorAuditCommitQuery' => 'applications/audit/query/commit',
'PhabricatorAuditCommitStatusConstants' => 'applications/audit/constants/commitstatus',
'PhabricatorAuditController' => 'applications/audit/controller/base',
'PhabricatorAuditDAO' => 'applications/audit/storage/base',
'PhabricatorAuditInlineComment' => 'applications/audit/storage/inlinecommment',
'PhabricatorAuditListController' => 'applications/audit/controller/list',
'PhabricatorAuditListView' => 'applications/audit/view/list',
'PhabricatorAuditPreviewController' => 'applications/audit/controller/preview',
'PhabricatorAuditQuery' => 'applications/audit/query/audit',
'PhabricatorAuditReplyHandler' => 'applications/audit/replyhandler',
'PhabricatorAuditStatusConstants' => 'applications/audit/constants/status',
'PhabricatorAuthController' => 'applications/auth/controller/base',
'PhabricatorCalendarBrowseController' => 'applications/calendar/controller/browse',
'PhabricatorCalendarController' => 'applications/calendar/controller/base',
'PhabricatorChangesetResponse' => 'infrastructure/diff/response',
'PhabricatorChatLogChannelListController' => 'applications/chatlog/controller/channellist',
'PhabricatorChatLogChannelLogController' => 'applications/chatlog/controller/channellog',
'PhabricatorChatLogConstants' => 'applications/chatlog/constants/base',
'PhabricatorChatLogController' => 'applications/chatlog/controller/base',
'PhabricatorChatLogDAO' => 'applications/chatlog/storage/base',
'PhabricatorChatLogEvent' => 'applications/chatlog/storage/event',
'PhabricatorChatLogEventType' => 'applications/chatlog/constants/eventtype',
'PhabricatorChatLogQuery' => 'applications/chatlog/query',
'PhabricatorConduitAPIController' => 'applications/conduit/controller/api',
'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/token',
'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/connectionlog',
'PhabricatorConduitConsoleController' => 'applications/conduit/controller/console',
'PhabricatorConduitController' => 'applications/conduit/controller/base',
'PhabricatorConduitDAO' => 'applications/conduit/storage/base',
'PhabricatorConduitLogController' => 'applications/conduit/controller/log',
'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/methodcalllog',
'PhabricatorConduitTokenController' => 'applications/conduit/controller/token',
'PhabricatorContentSource' => 'applications/metamta/contentsource/source',
'PhabricatorContentSourceView' => 'applications/metamta/contentsource/view',
'PhabricatorController' => 'applications/base/controller/base',
'PhabricatorCountdownController' => 'applications/countdown/controller/base',
'PhabricatorCountdownDAO' => 'applications/countdown/storage/base',
'PhabricatorCountdownDeleteController' => 'applications/countdown/controller/delete',
'PhabricatorCountdownEditController' => 'applications/countdown/controller/edit',
'PhabricatorCountdownListController' => 'applications/countdown/controller/list',
'PhabricatorCountdownViewController' => 'applications/countdown/controller/view',
'PhabricatorDaemon' => 'infrastructure/daemon/base',
'PhabricatorDaemonCombinedLogController' => 'applications/daemon/controller/combined',
'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/console',
'PhabricatorDaemonControl' => 'infrastructure/daemon/control',
'PhabricatorDaemonController' => 'applications/daemon/controller/base',
'PhabricatorDaemonDAO' => 'infrastructure/daemon/storage/base',
'PhabricatorDaemonLog' => 'infrastructure/daemon/storage/log',
'PhabricatorDaemonLogEvent' => 'infrastructure/daemon/storage/event',
'PhabricatorDaemonLogEventsView' => 'applications/daemon/view/daemonlogevents',
'PhabricatorDaemonLogListController' => 'applications/daemon/controller/loglist',
'PhabricatorDaemonLogListView' => 'applications/daemon/view/daemonloglist',
'PhabricatorDaemonLogViewController' => 'applications/daemon/controller/logview',
'PhabricatorDaemonReference' => 'infrastructure/daemon/control/reference',
'PhabricatorDaemonTimelineConsoleController' => 'applications/daemon/controller/timeline',
'PhabricatorDaemonTimelineEventController' => 'applications/daemon/controller/timelineevent',
'PhabricatorDefaultFileStorageEngineSelector' => 'applications/files/engineselector/default',
'PhabricatorDefaultSearchEngineSelector' => 'applications/search/selector/default',
'PhabricatorDifferenceEngine' => 'infrastructure/diff/engine',
'PhabricatorDirectoryCategory' => 'applications/directory/storage/category',
'PhabricatorDirectoryCategoryDeleteController' => 'applications/directory/controller/categorydelete',
'PhabricatorDirectoryCategoryEditController' => 'applications/directory/controller/categoryedit',
'PhabricatorDirectoryCategoryViewController' => 'applications/directory/controller/categoryview',
'PhabricatorDirectoryController' => 'applications/directory/controller/base',
'PhabricatorDirectoryDAO' => 'applications/directory/storage/base',
'PhabricatorDirectoryEditController' => 'applications/directory/controller/edit',
'PhabricatorDirectoryItem' => 'applications/directory/storage/item',
'PhabricatorDirectoryItemDeleteController' => 'applications/directory/controller/itemdelete',
'PhabricatorDirectoryItemEditController' => 'applications/directory/controller/itemedit',
'PhabricatorDirectoryMainController' => 'applications/directory/controller/main',
'PhabricatorDisabledUserController' => 'applications/auth/controller/disabled',
'PhabricatorDraft' => 'applications/draft/storage/draft',
'PhabricatorDraftDAO' => 'applications/draft/storage/base',
'PhabricatorEmailLoginController' => 'applications/auth/controller/email',
'PhabricatorEmailTokenController' => 'applications/auth/controller/emailtoken',
'PhabricatorEnv' => 'infrastructure/env',
'PhabricatorEnvTestCase' => 'infrastructure/env/__tests__',
'PhabricatorEvent' => 'infrastructure/events/event',
'PhabricatorEventEngine' => 'infrastructure/events/engine',
'PhabricatorEventType' => 'infrastructure/events/constant/type',
'PhabricatorFeedBuilder' => 'applications/feed/builder/feed',
'PhabricatorFeedConstants' => 'applications/feed/constants/base',
'PhabricatorFeedController' => 'applications/feed/controller/base',
'PhabricatorFeedDAO' => 'applications/feed/storage/base',
'PhabricatorFeedPublicStreamController' => 'applications/feed/controller/publicstream',
'PhabricatorFeedQuery' => 'applications/feed/query',
'PhabricatorFeedStory' => 'applications/feed/story/base',
'PhabricatorFeedStoryAudit' => 'applications/feed/story/audit',
'PhabricatorFeedStoryData' => 'applications/feed/storage/story',
'PhabricatorFeedStoryDifferential' => 'applications/feed/story/differential',
'PhabricatorFeedStoryManiphest' => 'applications/feed/story/maniphest',
'PhabricatorFeedStoryPhriction' => 'applications/feed/story/phriction',
'PhabricatorFeedStoryProject' => 'applications/feed/story/project',
'PhabricatorFeedStoryPublisher' => 'applications/feed/publisher',
'PhabricatorFeedStoryReference' => 'applications/feed/storage/storyreference',
'PhabricatorFeedStoryStatus' => 'applications/feed/story/status',
'PhabricatorFeedStoryTypeConstants' => 'applications/feed/constants/story',
'PhabricatorFeedStoryUnknown' => 'applications/feed/story/unknown',
'PhabricatorFeedStoryView' => 'applications/feed/view/story',
'PhabricatorFeedView' => 'applications/feed/view/base',
'PhabricatorFile' => 'applications/files/storage/file',
'PhabricatorFileController' => 'applications/files/controller/base',
'PhabricatorFileDAO' => 'applications/files/storage/base',
'PhabricatorFileDataController' => 'applications/files/controller/data',
'PhabricatorFileDeleteController' => 'applications/files/controller/delete',
'PhabricatorFileDropUploadController' => 'applications/files/controller/dropupload',
'PhabricatorFileImageMacro' => 'applications/files/storage/imagemacro',
'PhabricatorFileInfoController' => 'applications/files/controller/info',
'PhabricatorFileListController' => 'applications/files/controller/list',
'PhabricatorFileMacroDeleteController' => 'applications/files/controller/macrodelete',
'PhabricatorFileMacroEditController' => 'applications/files/controller/macroedit',
'PhabricatorFileMacroListController' => 'applications/files/controller/macrolist',
'PhabricatorFileProxyController' => 'applications/files/controller/proxy',
'PhabricatorFileProxyImage' => 'applications/files/storage/proxyimage',
'PhabricatorFileSideNavView' => 'applications/files/view/sidenav',
'PhabricatorFileStorageBlob' => 'applications/files/storage/storageblob',
'PhabricatorFileStorageEngine' => 'applications/files/engine/base',
'PhabricatorFileStorageEngineSelector' => 'applications/files/engineselector/base',
'PhabricatorFileTransformController' => 'applications/files/controller/transform',
'PhabricatorFileUploadController' => 'applications/files/controller/upload',
'PhabricatorFileUploadException' => 'applications/files/exception/upload',
'PhabricatorFileUploadView' => 'applications/files/view/upload',
'PhabricatorGarbageCollectorDaemon' => 'infrastructure/daemon/garbagecollector',
'PhabricatorGoodForNothingWorker' => 'infrastructure/daemon/workers/worker/goodfornothing',
'PhabricatorHandleObjectSelectorDataView' => 'applications/phid/handle/view/selector',
'PhabricatorHash' => 'infrastructure/util/hash',
'PhabricatorHelpController' => 'applications/help/controller/base',
'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/keyboardshortcut',
'PhabricatorIRCBot' => 'infrastructure/daemon/irc/bot',
'PhabricatorIRCDifferentialNotificationHandler' => 'infrastructure/daemon/irc/handler/differentialnotification',
'PhabricatorIRCHandler' => 'infrastructure/daemon/irc/handler/base',
'PhabricatorIRCLogHandler' => 'infrastructure/daemon/irc/handler/log',
'PhabricatorIRCMacroHandler' => 'infrastructure/daemon/irc/handler/macro',
'PhabricatorIRCMessage' => 'infrastructure/daemon/irc/message',
'PhabricatorIRCObjectNameHandler' => 'infrastructure/daemon/irc/handler/objectname',
'PhabricatorIRCProtocolHandler' => 'infrastructure/daemon/irc/handler/protocol',
'PhabricatorIRCWhatsNewHandler' => 'infrastructure/daemon/irc/handler/whatsnew',
'PhabricatorImageTransformer' => 'applications/files/transform',
'PhabricatorInfrastructureTestCase' => 'infrastructure/__tests__',
'PhabricatorInlineCommentController' => 'infrastructure/diff/controller',
'PhabricatorInlineCommentInterface' => 'infrastructure/diff/interface/inline',
'PhabricatorInlineSummaryView' => 'infrastructure/diff/view/inline',
'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/javelin',
'PhabricatorJumpNavHandler' => 'applications/search/engine/jumpnav',
'PhabricatorLintEngine' => 'infrastructure/lint/engine',
'PhabricatorLiskDAO' => 'applications/base/storage/lisk',
'PhabricatorLocalDiskFileStorageEngine' => 'applications/files/engine/localdisk',
'PhabricatorLocalTimeTestCase' => 'view/utils/__tests__',
'PhabricatorLoginController' => 'applications/auth/controller/login',
'PhabricatorLoginValidateController' => 'applications/auth/controller/validate',
'PhabricatorLogoutController' => 'applications/auth/controller/logout',
'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/base',
'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/amazonses',
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/phpmailerlite',
'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/sendgrid',
'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/test',
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/base',
'PhabricatorMarkupEngine' => 'applications/markup/engine',
'PhabricatorMetaMTAAttachment' => 'applications/metamta/storage/mail',
'PhabricatorMetaMTAController' => 'applications/metamta/controller/base',
'PhabricatorMetaMTADAO' => 'applications/metamta/storage/base',
'PhabricatorMetaMTAEmailBodyParser' => 'applications/metamta/parser',
'PhabricatorMetaMTAEmailBodyParserTestCase' => 'applications/metamta/parser/__tests__',
'PhabricatorMetaMTAListController' => 'applications/metamta/controller/list',
'PhabricatorMetaMTAMail' => 'applications/metamta/storage/mail',
'PhabricatorMetaMTAMailTestCase' => 'applications/metamta/storage/mail/__tests__',
'PhabricatorMetaMTAMailingList' => 'applications/metamta/storage/mailinglist',
'PhabricatorMetaMTAMailingListEditController' => 'applications/metamta/controller/mailinglistedit',
'PhabricatorMetaMTAMailingListsController' => 'applications/metamta/controller/mailinglists',
'PhabricatorMetaMTAReceiveController' => 'applications/metamta/controller/receive',
'PhabricatorMetaMTAReceivedListController' => 'applications/metamta/controller/receivedlist',
'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/receivedmail',
'PhabricatorMetaMTASendController' => 'applications/metamta/controller/send',
'PhabricatorMetaMTASendGridReceiveController' => 'applications/metamta/controller/sendgridreceive',
'PhabricatorMetaMTAViewController' => 'applications/metamta/controller/view',
'PhabricatorMetaMTAWorker' => 'applications/metamta/worker',
'PhabricatorMySQLFileStorageEngine' => 'applications/files/engine/mysql',
'PhabricatorNotificationsController' => 'applications/notifications/controller/base',
'PhabricatorOAuthClientAuthorization' => 'applications/oauthserver/storage/clientauthorization',
'PhabricatorOAuthClientAuthorizationBaseController' => 'applications/oauthserver/controller/clientauthorization/base',
'PhabricatorOAuthClientAuthorizationDeleteController' => 'applications/oauthserver/controller/clientauthorization/delete',
'PhabricatorOAuthClientAuthorizationEditController' => 'applications/oauthserver/controller/clientauthorization/edit',
'PhabricatorOAuthClientAuthorizationListController' => 'applications/oauthserver/controller/clientauthorization/list',
'PhabricatorOAuthClientBaseController' => 'applications/oauthserver/controller/client/base',
'PhabricatorOAuthClientDeleteController' => 'applications/oauthserver/controller/client/delete',
'PhabricatorOAuthClientEditController' => 'applications/oauthserver/controller/client/edit',
'PhabricatorOAuthClientListController' => 'applications/oauthserver/controller/client/list',
'PhabricatorOAuthClientViewController' => 'applications/oauthserver/controller/client/view',
'PhabricatorOAuthDefaultRegistrationController' => 'applications/auth/controller/oauthregistration/default',
'PhabricatorOAuthDiagnosticsController' => 'applications/auth/controller/oauthdiagnostics',
'PhabricatorOAuthFailureView' => 'applications/auth/view/oauthfailure',
'PhabricatorOAuthLoginController' => 'applications/auth/controller/oauth',
'PhabricatorOAuthProvider' => 'applications/auth/oauth/provider/base',
'PhabricatorOAuthProviderFacebook' => 'applications/auth/oauth/provider/facebook',
'PhabricatorOAuthProviderGitHub' => 'applications/auth/oauth/provider/github',
'PhabricatorOAuthProviderGoogle' => 'applications/auth/oauth/provider/google',
'PhabricatorOAuthProviderPhabricator' => 'applications/auth/oauth/provider/phabricator',
'PhabricatorOAuthRegistrationController' => 'applications/auth/controller/oauthregistration/base',
'PhabricatorOAuthResponse' => 'applications/oauthserver/response',
'PhabricatorOAuthServer' => 'applications/oauthserver/server',
'PhabricatorOAuthServerAccessToken' => 'applications/oauthserver/storage/accesstoken',
'PhabricatorOAuthServerAuthController' => 'applications/oauthserver/controller/auth',
'PhabricatorOAuthServerAuthorizationCode' => 'applications/oauthserver/storage/authorizationcode',
'PhabricatorOAuthServerClient' => 'applications/oauthserver/storage/client',
'PhabricatorOAuthServerController' => 'applications/oauthserver/controller/base',
'PhabricatorOAuthServerDAO' => 'applications/oauthserver/storage/base',
'PhabricatorOAuthServerScope' => 'applications/oauthserver/scope',
'PhabricatorOAuthServerTestCase' => 'applications/oauthserver/server/__tests__',
'PhabricatorOAuthServerTestController' => 'applications/oauthserver/controller/test',
'PhabricatorOAuthServerTokenController' => 'applications/oauthserver/controller/token',
'PhabricatorOAuthUnlinkController' => 'applications/auth/controller/unlink',
'PhabricatorObjectAttachmentEditor' => 'applications/search/editor/attach',
'PhabricatorObjectGraph' => 'applications/phid/graph',
'PhabricatorObjectHandle' => 'applications/phid/handle',
'PhabricatorObjectHandleConstants' => 'applications/phid/handle/const/base',
'PhabricatorObjectHandleData' => 'applications/phid/handle/data',
'PhabricatorObjectHandleStatus' => 'applications/phid/handle/const/status',
'PhabricatorObjectSelectorDialog' => 'view/control/objectselector',
'PhabricatorOwnerPathQuery' => 'applications/owners/query/path',
'PhabricatorOwnersController' => 'applications/owners/controller/base',
'PhabricatorOwnersDAO' => 'applications/owners/storage/base',
'PhabricatorOwnersDeleteController' => 'applications/owners/controller/delete',
'PhabricatorOwnersDetailController' => 'applications/owners/controller/detail',
'PhabricatorOwnersEditController' => 'applications/owners/controller/edit',
'PhabricatorOwnersListController' => 'applications/owners/controller/list',
'PhabricatorOwnersOwner' => 'applications/owners/storage/owner',
'PhabricatorOwnersPackage' => 'applications/owners/storage/package',
'PhabricatorOwnersPath' => 'applications/owners/storage/path',
'PhabricatorPHID' => 'applications/phid/storage/phid',
'PhabricatorPHIDConstants' => 'applications/phid/constants',
'PhabricatorPHIDController' => 'applications/phid/controller/base',
'PhabricatorPHIDDAO' => 'applications/phid/storage/base',
'PhabricatorPHIDLookupController' => 'applications/phid/controller/lookup',
'PhabricatorPaste' => 'applications/paste/storage/paste',
'PhabricatorPasteController' => 'applications/paste/controller/base',
'PhabricatorPasteDAO' => 'applications/paste/storage/base',
'PhabricatorPasteListController' => 'applications/paste/controller/list',
'PhabricatorPasteViewController' => 'applications/paste/controller/view',
'PhabricatorPeopleController' => 'applications/people/controller/base',
'PhabricatorPeopleEditController' => 'applications/people/controller/edit',
'PhabricatorPeopleListController' => 'applications/people/controller/list',
'PhabricatorPeopleLogsController' => 'applications/people/controller/logs',
'PhabricatorPeopleProfileController' => 'applications/people/controller/profile',
'PhabricatorProfileHeaderView' => 'view/layout/profileheader',
'PhabricatorProject' => 'applications/project/storage/project',
'PhabricatorProjectAffiliation' => 'applications/project/storage/affiliation',
'PhabricatorProjectConstants' => 'applications/project/constants/base',
'PhabricatorProjectController' => 'applications/project/controller/base',
'PhabricatorProjectCreateController' => 'applications/project/controller/create',
'PhabricatorProjectDAO' => 'applications/project/storage/base',
'PhabricatorProjectEditor' => 'applications/project/editor/project',
'PhabricatorProjectListController' => 'applications/project/controller/list',
'PhabricatorProjectNameCollisionException' => 'applications/project/exception/namecollison',
'PhabricatorProjectProfile' => 'applications/project/storage/profile',
'PhabricatorProjectProfileController' => 'applications/project/controller/profile',
'PhabricatorProjectProfileEditController' => 'applications/project/controller/profileedit',
'PhabricatorProjectQuery' => 'applications/project/query/project',
'PhabricatorProjectStatus' => 'applications/project/constants/status',
'PhabricatorProjectSubproject' => 'applications/project/storage/subproject',
'PhabricatorProjectTransaction' => 'applications/project/storage/transaction',
'PhabricatorProjectTransactionType' => 'applications/project/constants/transaction',
'PhabricatorProjectUpdateController' => 'applications/project/controller/update',
'PhabricatorRedirectController' => 'applications/base/controller/redirect',
'PhabricatorRefreshCSRFController' => 'applications/auth/controller/refresh',
'PhabricatorRemarkupRuleDifferential' => 'infrastructure/markup/remarkup/markuprule/differential',
'PhabricatorRemarkupRuleDifferentialHandle' => 'infrastructure/markup/remarkup/markuprule/handle/differential',
'PhabricatorRemarkupRuleDiffusion' => 'infrastructure/markup/remarkup/markuprule/diffusion',
'PhabricatorRemarkupRuleEmbedFile' => 'infrastructure/markup/remarkup/markuprule/embedobject',
'PhabricatorRemarkupRuleImageMacro' => 'infrastructure/markup/remarkup/markuprule/imagemacro',
'PhabricatorRemarkupRuleManiphest' => 'infrastructure/markup/remarkup/markuprule/maniphest',
'PhabricatorRemarkupRuleManiphestHandle' => 'infrastructure/markup/remarkup/markuprule/handle/maniphest',
'PhabricatorRemarkupRuleMention' => 'infrastructure/markup/remarkup/markuprule/mention',
'PhabricatorRemarkupRuleObjectHandle' => 'infrastructure/markup/remarkup/markuprule/handle',
'PhabricatorRemarkupRuleObjectName' => 'infrastructure/markup/remarkup/markuprule/objectname',
'PhabricatorRemarkupRulePaste' => 'infrastructure/markup/remarkup/markuprule/paste',
'PhabricatorRemarkupRulePhriction' => 'infrastructure/markup/remarkup/markuprule/phriction',
'PhabricatorRemarkupRuleProxyImage' => 'infrastructure/markup/remarkup/markuprule/proxyimage',
'PhabricatorRemarkupRuleYoutube' => 'infrastructure/markup/remarkup/markuprule/youtube',
'PhabricatorRepository' => 'applications/repository/storage/repository',
'PhabricatorRepositoryArcanistProject' => 'applications/repository/storage/arcanistproject',
'PhabricatorRepositoryArcanistProjectEditController' => 'applications/repository/controller/arcansistprojectedit',
'PhabricatorRepositoryAuditRequest' => 'applications/repository/storage/auditrequest',
'PhabricatorRepositoryCommit' => 'applications/repository/storage/commit',
'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/base',
'PhabricatorRepositoryCommitData' => 'applications/repository/storage/commitdata',
'PhabricatorRepositoryCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/base',
'PhabricatorRepositoryCommitHeraldWorker' => 'applications/repository/worker/herald',
'PhabricatorRepositoryCommitMessageDetailParser' => 'applications/repository/parser/base',
'PhabricatorRepositoryCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/base',
'PhabricatorRepositoryCommitOwnersWorker' => 'applications/repository/worker/owner',
'PhabricatorRepositoryCommitParserWorker' => 'applications/repository/worker/base',
'PhabricatorRepositoryCommitTaskDaemon' => 'applications/repository/daemon/committask',
'PhabricatorRepositoryController' => 'applications/repository/controller/base',
'PhabricatorRepositoryCreateController' => 'applications/repository/controller/create',
'PhabricatorRepositoryDAO' => 'applications/repository/storage/base',
'PhabricatorRepositoryDaemon' => 'applications/repository/daemon/base',
'PhabricatorRepositoryDefaultCommitMessageDetailParser' => 'applications/repository/parser/default',
'PhabricatorRepositoryDeleteController' => 'applications/repository/controller/delete',
'PhabricatorRepositoryEditController' => 'applications/repository/controller/edit',
'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/git',
'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/git',
'PhabricatorRepositoryGitCommitDiscoveryDaemonTestCase' => 'applications/repository/daemon/commitdiscovery/git/__tests__',
'PhabricatorRepositoryGitCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/git',
'PhabricatorRepositoryGitFetchDaemon' => 'applications/repository/daemon/gitfetch',
'PhabricatorRepositoryListController' => 'applications/repository/controller/list',
'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/mercurial',
'PhabricatorRepositoryMercurialCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/mercurial',
'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/mercurial',
'PhabricatorRepositoryMercurialPullDaemon' => 'applications/repository/daemon/mercurialpull',
'PhabricatorRepositoryPullLocalDaemon' => 'applications/repository/daemon/pulllocal',
'PhabricatorRepositoryShortcut' => 'applications/repository/storage/shortcut',
'PhabricatorRepositorySvnCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/svn',
'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/svn',
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/svn',
'PhabricatorRepositorySymbol' => 'applications/repository/storage/symbol',
'PhabricatorRepositoryTestCase' => 'applications/repository/storage/repository/__tests__',
'PhabricatorRepositoryType' => 'applications/repository/constants/repositorytype',
'PhabricatorS3FileStorageEngine' => 'applications/files/engine/s3',
'PhabricatorSQLPatchList' => 'infrastructure/setup/sql',
'PhabricatorSearchAbstractDocument' => 'applications/search/index/abstractdocument',
'PhabricatorSearchAttachController' => 'applications/search/controller/attach',
'PhabricatorSearchBaseController' => 'applications/search/controller/base',
'PhabricatorSearchCommitIndexer' => 'applications/search/index/indexer/repository',
'PhabricatorSearchController' => 'applications/search/controller/search',
'PhabricatorSearchDAO' => 'applications/search/storage/base',
'PhabricatorSearchDifferentialIndexer' => 'applications/search/index/indexer/differential',
'PhabricatorSearchDocument' => 'applications/search/storage/document/document',
'PhabricatorSearchDocumentField' => 'applications/search/storage/document/field',
'PhabricatorSearchDocumentIndexer' => 'applications/search/index/indexer/base',
'PhabricatorSearchDocumentRelationship' => 'applications/search/storage/document/relationship',
'PhabricatorSearchEngine' => 'applications/search/engine/base',
'PhabricatorSearchEngineMySQL' => 'applications/search/engine/mysql',
'PhabricatorSearchEngineSelector' => 'applications/search/selector/base',
'PhabricatorSearchField' => 'applications/search/constants/field',
'PhabricatorSearchIndexController' => 'applications/search/controller/index',
'PhabricatorSearchManiphestIndexer' => 'applications/search/index/indexer/maniphest',
'PhabricatorSearchPhrictionIndexer' => 'applications/search/index/indexer/phriction',
'PhabricatorSearchQuery' => 'applications/search/storage/query',
'PhabricatorSearchRelationship' => 'applications/search/constants/relationship',
'PhabricatorSearchResultView' => 'applications/search/view/searchresult',
'PhabricatorSearchScope' => 'applications/search/constants/scope',
'PhabricatorSearchSelectController' => 'applications/search/controller/select',
'PhabricatorSearchUserIndexer' => 'applications/search/index/indexer/user',
'PhabricatorSetup' => 'infrastructure/setup',
'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/choice',
'PhabricatorSlowvoteComment' => 'applications/slowvote/storage/comment',
'PhabricatorSlowvoteController' => 'applications/slowvote/controller/base',
'PhabricatorSlowvoteCreateController' => 'applications/slowvote/controller/create',
'PhabricatorSlowvoteDAO' => 'applications/slowvote/storage/base',
'PhabricatorSlowvoteListController' => 'applications/slowvote/controller/list',
'PhabricatorSlowvoteOption' => 'applications/slowvote/storage/option',
'PhabricatorSlowvotePoll' => 'applications/slowvote/storage/poll',
'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/poll',
'PhabricatorSortTableExample' => 'applications/uiexample/examples/sorttable',
'PhabricatorStandardPageView' => 'view/page/standard',
'PhabricatorStatusController' => 'applications/status/base',
'PhabricatorSymbolNameLinter' => 'infrastructure/lint/hook/xhpastsymbolname',
'PhabricatorSyntaxHighlighter' => 'applications/markup/syntax',
'PhabricatorTaskmasterDaemon' => 'infrastructure/daemon/workers/taskmaster',
'PhabricatorTestCase' => 'infrastructure/testing/testcase',
'PhabricatorTimelineCursor' => 'infrastructure/daemon/timeline/storage/cursor',
'PhabricatorTimelineDAO' => 'infrastructure/daemon/timeline/storage/base',
'PhabricatorTimelineEvent' => 'infrastructure/daemon/timeline/storage/event',
'PhabricatorTimelineEventData' => 'infrastructure/daemon/timeline/storage/eventdata',
'PhabricatorTimelineIterator' => 'infrastructure/daemon/timeline/cursor/iterator',
'PhabricatorTimer' => 'applications/countdown/storage/timer',
'PhabricatorTransactionView' => 'view/layout/transaction',
'PhabricatorTransformedFile' => 'applications/files/storage/transformed',
'PhabricatorTrivialTestCase' => 'infrastructure/testing/testcase/__tests__',
'PhabricatorTypeaheadCommonDatasourceController' => 'applications/typeahead/controller/common',
'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/base',
'PhabricatorUIExample' => 'applications/uiexample/examples/base',
'PhabricatorUIExampleController' => 'applications/uiexample/controller/base',
'PhabricatorUIExampleRenderController' => 'applications/uiexample/controller/render',
'PhabricatorUIListFilterExample' => 'applications/uiexample/examples/listfilter',
'PhabricatorUIPagerExample' => 'applications/uiexample/examples/pager',
'PhabricatorUITooltipExample' => 'applications/uiexample/examples/tooltip',
'PhabricatorUser' => 'applications/people/storage/user',
'PhabricatorUserAccountSettingsPanelController' => 'applications/people/controller/settings/panels/account',
'PhabricatorUserConduitSettingsPanelController' => 'applications/people/controller/settings/panels/conduit',
'PhabricatorUserDAO' => 'applications/people/storage/base',
'PhabricatorUserEmailPreferenceSettingsPanelController' => 'applications/people/controller/settings/panels/emailpref',
'PhabricatorUserEmailSettingsPanelController' => 'applications/people/controller/settings/panels/email',
'PhabricatorUserLog' => 'applications/people/storage/log',
'PhabricatorUserOAuthInfo' => 'applications/people/storage/useroauthinfo',
'PhabricatorUserOAuthSettingsPanelController' => 'applications/people/controller/settings/panels/oauth',
'PhabricatorUserPasswordSettingsPanelController' => 'applications/people/controller/settings/panels/password',
'PhabricatorUserPreferenceSettingsPanelController' => 'applications/people/controller/settings/panels/preferences',
'PhabricatorUserPreferences' => 'applications/people/storage/preferences',
'PhabricatorUserProfile' => 'applications/people/storage/profile',
'PhabricatorUserProfileSettingsPanelController' => 'applications/people/controller/settings/panels/profile',
'PhabricatorUserSSHKey' => 'applications/people/storage/usersshkey',
'PhabricatorUserSSHKeysSettingsPanelController' => 'applications/people/controller/settings/panels/sshkeys',
'PhabricatorUserSearchSettingsPanelController' => 'applications/people/controller/settings/panels/search',
'PhabricatorUserSettingsController' => 'applications/people/controller/settings',
'PhabricatorUserSettingsPanelController' => 'applications/people/controller/settings/panels/base',
'PhabricatorUserTestCase' => 'applications/people/storage/user/__tests__',
'PhabricatorWorker' => 'infrastructure/daemon/workers/worker',
'PhabricatorWorkerDAO' => 'infrastructure/daemon/workers/storage/base',
'PhabricatorWorkerTask' => 'infrastructure/daemon/workers/storage/task',
'PhabricatorWorkerTaskData' => 'infrastructure/daemon/workers/storage/taskdata',
'PhabricatorWorkerTaskDetailController' => 'applications/daemon/controller/workertaskdetail',
'PhabricatorWorkerTaskUpdateController' => 'applications/daemon/controller/workertaskupdate',
'PhabricatorXHPASTViewController' => 'applications/xhpastview/controller/base',
'PhabricatorXHPASTViewDAO' => 'applications/xhpastview/storage/base',
'PhabricatorXHPASTViewFrameController' => 'applications/xhpastview/controller/viewframe',
'PhabricatorXHPASTViewFramesetController' => 'applications/xhpastview/controller/viewframeset',
'PhabricatorXHPASTViewInputController' => 'applications/xhpastview/controller/viewinput',
'PhabricatorXHPASTViewPanelController' => 'applications/xhpastview/controller/viewpanel',
'PhabricatorXHPASTViewParseTree' => 'applications/xhpastview/storage/parsetree',
'PhabricatorXHPASTViewRunController' => 'applications/xhpastview/controller/run',
'PhabricatorXHPASTViewStreamController' => 'applications/xhpastview/controller/viewstream',
'PhabricatorXHPASTViewTreeController' => 'applications/xhpastview/controller/viewtree',
'PhabricatorXHProfController' => 'applications/xhprof/controller/base',
'PhabricatorXHProfProfileController' => 'applications/xhprof/controller/profile',
'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/symbol',
'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/toplevel',
'PhabricatorXHProfProfileView' => 'applications/xhprof/view/base',
'PhrictionActionConstants' => 'applications/phriction/constants/action',
'PhrictionChangeType' => 'applications/phriction/constants/changetype',
'PhrictionConstants' => 'applications/phriction/constants/base',
'PhrictionContent' => 'applications/phriction/storage/content',
'PhrictionController' => 'applications/phriction/controller/base',
'PhrictionDAO' => 'applications/phriction/storage/base',
'PhrictionDeleteController' => 'applications/phriction/controller/delete',
'PhrictionDiffController' => 'applications/phriction/controller/diff',
'PhrictionDocument' => 'applications/phriction/storage/document',
'PhrictionDocumentController' => 'applications/phriction/controller/document',
'PhrictionDocumentEditor' => 'applications/phriction/editor/document',
'PhrictionDocumentPreviewController' => 'applications/phriction/controller/documentpreview',
'PhrictionDocumentStatus' => 'applications/phriction/constants/documentstatus',
'PhrictionDocumentTestCase' => 'applications/phriction/storage/document/__tests__',
'PhrictionEditController' => 'applications/phriction/controller/edit',
'PhrictionHistoryController' => 'applications/phriction/controller/history',
'PhrictionListController' => 'applications/phriction/controller/list',
'QueryFormattingTestCase' => 'storage/qsprintf/__tests__',
),
'function' =>
array(
'__phabricator_format_local_time' => 'view/utils',
'_qsprintf_check_scalar_type' => 'storage/qsprintf',
'_qsprintf_check_type' => 'storage/qsprintf',
'celerity_generate_unique_node_id' => 'infrastructure/celerity/api',
'celerity_register_resource_map' => 'infrastructure/celerity/map',
'javelin_render_tag' => 'infrastructure/javelin/markup',
'phabricator_date' => 'view/utils',
'phabricator_datetime' => 'view/utils',
'phabricator_format_relative_time' => 'view/utils',
'phabricator_format_units_generic' => 'view/utils',
'phabricator_render_form' => 'infrastructure/javelin/markup',
'phabricator_time' => 'view/utils',
'qsprintf' => 'storage/qsprintf',
'queryfx' => 'storage/queryfx',
'queryfx_all' => 'storage/queryfx',
'queryfx_one' => 'storage/queryfx',
'require_celerity_resource' => 'infrastructure/celerity/api',
'vqsprintf' => 'storage/qsprintf',
'vqueryfx' => 'storage/queryfx',
'vqueryfx_all' => 'storage/queryfx',
'xsprintf_query' => 'storage/qsprintf',
),
'requires_class' =>
array(
'Aphront304Response' => 'AphrontResponse',
'Aphront400Response' => 'AphrontResponse',
'Aphront403Response' => 'AphrontWebpageResponse',
'Aphront404Response' => 'AphrontWebpageResponse',
'AphrontAjaxResponse' => 'AphrontResponse',
'AphrontAttachedFileView' => 'AphrontView',
'AphrontCSRFException' => 'AphrontException',
'AphrontCalendarMonthView' => 'AphrontView',
'AphrontContextBarView' => 'AphrontView',
'AphrontCrumbsView' => 'AphrontView',
'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration',
'AphrontDialogResponse' => 'AphrontResponse',
'AphrontDialogView' => 'AphrontView',
'AphrontErrorView' => 'AphrontView',
'AphrontFilePreviewView' => 'AphrontView',
'AphrontFileResponse' => 'AphrontResponse',
'AphrontFormCheckboxControl' => 'AphrontFormControl',
'AphrontFormControl' => 'AphrontView',
'AphrontFormDividerControl' => 'AphrontFormControl',
'AphrontFormDragAndDropUploadControl' => 'AphrontFormControl',
'AphrontFormFileControl' => 'AphrontFormControl',
'AphrontFormInsetView' => 'AphrontView',
'AphrontFormLayoutView' => 'AphrontView',
'AphrontFormMarkupControl' => 'AphrontFormControl',
'AphrontFormPasswordControl' => 'AphrontFormControl',
'AphrontFormRadioButtonControl' => 'AphrontFormControl',
'AphrontFormRecaptchaControl' => 'AphrontFormControl',
'AphrontFormSelectControl' => 'AphrontFormControl',
'AphrontFormStaticControl' => 'AphrontFormControl',
'AphrontFormSubmitControl' => 'AphrontFormControl',
'AphrontFormTextAreaControl' => 'AphrontFormControl',
'AphrontFormTextControl' => 'AphrontFormControl',
'AphrontFormToggleButtonsControl' => 'AphrontFormControl',
'AphrontFormTokenizerControl' => 'AphrontFormControl',
'AphrontFormView' => 'AphrontView',
'AphrontHTTPSinkTestCase' => 'PhabricatorTestCase',
'AphrontHeadsupActionListView' => 'AphrontView',
'AphrontHeadsupActionView' => 'AphrontView',
'AphrontIsolatedDatabaseConnection' => 'AphrontDatabaseConnection',
'AphrontIsolatedDatabaseConnectionTestCase' => 'PhabricatorTestCase',
'AphrontIsolatedHTTPSink' => 'AphrontHTTPSink',
'AphrontJSONResponse' => 'AphrontResponse',
'AphrontJavelinView' => 'AphrontView',
'AphrontKeyboardShortcutsAvailableView' => 'AphrontView',
'AphrontListFilterView' => 'AphrontView',
'AphrontMiniPanelView' => 'AphrontView',
'AphrontMySQLDatabaseConnection' => 'AphrontDatabaseConnection',
'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase',
'AphrontNullView' => 'AphrontView',
'AphrontPHPHTTPSink' => 'AphrontHTTPSink',
'AphrontPageView' => 'AphrontView',
'AphrontPagerView' => 'AphrontView',
'AphrontPanelView' => 'AphrontView',
'AphrontPlainTextResponse' => 'AphrontResponse',
'AphrontProxyResponse' => 'AphrontResponse',
'AphrontQueryAccessDeniedException' => 'AphrontQueryRecoverableException',
'AphrontQueryConnectionException' => 'AphrontQueryException',
'AphrontQueryConnectionLostException' => 'AphrontQueryRecoverableException',
'AphrontQueryCountException' => 'AphrontQueryException',
'AphrontQueryDuplicateKeyException' => 'AphrontQueryException',
'AphrontQueryObjectMissingException' => 'AphrontQueryException',
'AphrontQueryParameterException' => 'AphrontQueryException',
'AphrontQueryRecoverableException' => 'AphrontQueryException',
'AphrontQuerySchemaException' => 'AphrontQueryException',
'AphrontRedirectException' => 'AphrontException',
'AphrontRedirectResponse' => 'AphrontResponse',
'AphrontReloadResponse' => 'AphrontRedirectResponse',
'AphrontRequestFailureView' => 'AphrontView',
'AphrontRequestTestCase' => 'PhabricatorTestCase',
'AphrontSideNavFilterView' => 'AphrontView',
'AphrontSideNavView' => 'AphrontView',
'AphrontTableView' => 'AphrontView',
'AphrontTokenizerTemplateView' => 'AphrontView',
'AphrontTypeaheadTemplateView' => 'AphrontView',
'AphrontWebpageResponse' => 'AphrontResponse',
'CelerityResourceController' => 'AphrontController',
'CelerityResourceGraph' => 'AbstractDirectedGraph',
'ConduitAPI_arcanist_Method' => 'ConduitAPIMethod',
'ConduitAPI_arcanist_projectinfo_Method' => 'ConduitAPI_arcanist_Method',
'ConduitAPI_audit_Method' => 'ConduitAPIMethod',
'ConduitAPI_audit_query_Method' => 'ConduitAPI_audit_Method',
'ConduitAPI_chatlog_Method' => 'ConduitAPIMethod',
'ConduitAPI_chatlog_query_Method' => 'ConduitAPI_chatlog_Method',
'ConduitAPI_chatlog_record_Method' => 'ConduitAPI_chatlog_Method',
'ConduitAPI_conduit_connect_Method' => 'ConduitAPIMethod',
'ConduitAPI_conduit_getcertificate_Method' => 'ConduitAPIMethod',
'ConduitAPI_conduit_ping_Method' => 'ConduitAPIMethod',
'ConduitAPI_daemon_launched_Method' => 'ConduitAPIMethod',
'ConduitAPI_daemon_log_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_createcomment_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_creatediff_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_createrevision_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_find_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getalldiffs_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getcommitmessage_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getcommitpaths_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getdiff_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getrevision_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getrevisioncomments_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getrevisionfeedback_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_markcommitted_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_parsecommitmessage_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_query_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_setdiffproperty_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_updaterevision_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_updatetaskrevisionassoc_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_updateunitresults_Method' => 'ConduitAPIMethod',
'ConduitAPI_diffusion_findsymbols_Method' => 'ConduitAPIMethod',
'ConduitAPI_diffusion_getcommits_Method' => 'ConduitAPIMethod',
'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'ConduitAPIMethod',
'ConduitAPI_feed_publish_Method' => 'ConduitAPIMethod',
'ConduitAPI_feed_query_Method' => 'ConduitAPIMethod',
'ConduitAPI_file_download_Method' => 'ConduitAPIMethod',
'ConduitAPI_file_info_Method' => 'ConduitAPIMethod',
'ConduitAPI_file_upload_Method' => 'ConduitAPIMethod',
'ConduitAPI_macro_Method' => 'ConduitAPIMethod',
'ConduitAPI_macro_query_Method' => 'ConduitAPI_macro_Method',
'ConduitAPI_maniphest_Method' => 'ConduitAPIMethod',
'ConduitAPI_maniphest_createtask_Method' => 'ConduitAPI_maniphest_Method',
'ConduitAPI_maniphest_find_Method' => 'ConduitAPI_maniphest_Method',
'ConduitAPI_maniphest_gettasktransactions_Method' => 'ConduitAPI_maniphest_Method',
'ConduitAPI_maniphest_info_Method' => 'ConduitAPI_maniphest_Method',
'ConduitAPI_maniphest_update_Method' => 'ConduitAPI_maniphest_Method',
'ConduitAPI_paste_Method' => 'ConduitAPIMethod',
'ConduitAPI_paste_create_Method' => 'ConduitAPI_paste_Method',
'ConduitAPI_paste_info_Method' => 'ConduitAPI_paste_Method',
'ConduitAPI_path_getowners_Method' => 'ConduitAPIMethod',
'ConduitAPI_phid_Method' => 'ConduitAPIMethod',
'ConduitAPI_phid_info_Method' => 'ConduitAPI_phid_Method',
'ConduitAPI_phid_query_Method' => 'ConduitAPI_phid_Method',
'ConduitAPI_phriction_Method' => 'ConduitAPIMethod',
'ConduitAPI_phriction_edit_Method' => 'ConduitAPI_phriction_Method',
'ConduitAPI_phriction_history_Method' => 'ConduitAPI_phriction_Method',
'ConduitAPI_phriction_info_Method' => 'ConduitAPI_phriction_Method',
'ConduitAPI_project_Method' => 'ConduitAPIMethod',
'ConduitAPI_project_query_Method' => 'ConduitAPI_project_Method',
'ConduitAPI_remarkup_process_Method' => 'ConduitAPIMethod',
'ConduitAPI_slowvote_info_Method' => 'ConduitAPIMethod',
'ConduitAPI_user_Method' => 'ConduitAPIMethod',
'ConduitAPI_user_find_Method' => 'ConduitAPI_user_Method',
'ConduitAPI_user_info_Method' => 'ConduitAPI_user_Method',
'ConduitAPI_user_whoami_Method' => 'ConduitAPI_user_Method',
'DarkConsoleConfigPlugin' => 'DarkConsolePlugin',
'DarkConsoleController' => 'PhabricatorController',
'DarkConsoleErrorLogPlugin' => 'DarkConsolePlugin',
'DarkConsoleEventPlugin' => 'DarkConsolePlugin',
'DarkConsoleEventPluginAPI' => 'PhutilEventListener',
'DarkConsoleRequestPlugin' => 'DarkConsolePlugin',
'DarkConsoleServicesPlugin' => 'DarkConsolePlugin',
'DarkConsoleXHProfPlugin' => 'DarkConsolePlugin',
'DifferentialActionHasNoEffectException' => 'DifferentialException',
'DifferentialAddCommentView' => 'AphrontView',
'DifferentialAffectedPath' => 'DifferentialDAO',
'DifferentialApplyPatchFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialArcanistProjectFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialAuditorsFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialAuthorFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialAuxiliaryField' => 'DifferentialDAO',
'DifferentialBlameRevisionFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialBranchFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialCCWelcomeMail' => 'DifferentialReviewRequestMail',
'DifferentialCCsFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialChangeset' => 'DifferentialDAO',
'DifferentialChangesetDetailView' => 'AphrontView',
'DifferentialChangesetListView' => 'AphrontView',
'DifferentialChangesetViewController' => 'DifferentialController',
'DifferentialComment' => 'DifferentialDAO',
'DifferentialCommentMail' => 'DifferentialMail',
'DifferentialCommentPreviewController' => 'DifferentialController',
'DifferentialCommentSaveController' => 'DifferentialController',
'DifferentialCommitsFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialController' => 'PhabricatorController',
'DifferentialDAO' => 'PhabricatorLiskDAO',
'DifferentialDateCreatedFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialDateModifiedFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialDefaultFieldSelector' => 'DifferentialFieldSelector',
'DifferentialDependenciesFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialDiff' => 'DifferentialDAO',
'DifferentialDiffContentMail' => 'DifferentialMail',
'DifferentialDiffCreateController' => 'DifferentialController',
'DifferentialDiffProperty' => 'DifferentialDAO',
'DifferentialDiffTableOfContentsView' => 'AphrontView',
'DifferentialDiffViewController' => 'DifferentialController',
'DifferentialExceptionMail' => 'DifferentialMail',
'DifferentialExportPatchFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialGitSVNIDFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialHostFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialHunk' => 'DifferentialDAO',
'DifferentialInlineComment' => 'DifferentialDAO',
'DifferentialInlineCommentEditController' => 'PhabricatorInlineCommentController',
'DifferentialInlineCommentEditView' => 'AphrontView',
'DifferentialInlineCommentPreviewController' => 'DifferentialController',
'DifferentialInlineCommentView' => 'AphrontView',
'DifferentialLinesFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialLintFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialLocalCommitsView' => 'AphrontView',
'DifferentialManiphestTasksFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialNewDiffMail' => 'DifferentialReviewRequestMail',
'DifferentialPathFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialPrimaryPaneView' => 'AphrontView',
'DifferentialReplyHandler' => 'PhabricatorMailReplyHandler',
'DifferentialRevertPlanFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialReviewRequestMail' => 'DifferentialMail',
'DifferentialReviewedByFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialReviewersFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialRevision' => 'DifferentialDAO',
'DifferentialRevisionCommentListView' => 'AphrontView',
'DifferentialRevisionCommentView' => 'AphrontView',
'DifferentialRevisionDetailView' => 'AphrontView',
'DifferentialRevisionEditController' => 'DifferentialController',
'DifferentialRevisionIDFieldParserTestCase' => 'PhabricatorTestCase',
'DifferentialRevisionIDFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialRevisionListController' => 'DifferentialController',
'DifferentialRevisionListView' => 'AphrontView',
'DifferentialRevisionStatsController' => 'DifferentialController',
'DifferentialRevisionStatsView' => 'AphrontView',
'DifferentialRevisionStatusFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialRevisionUpdateHistoryView' => 'AphrontView',
'DifferentialRevisionViewController' => 'DifferentialController',
'DifferentialSubscribeController' => 'DifferentialController',
'DifferentialSummaryFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialTestPlanFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialTitleFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialUnitFieldSpecification' => 'DifferentialFieldSpecification',
'DiffusionBranchTableView' => 'DiffusionView',
'DiffusionBrowseController' => 'DiffusionController',
'DiffusionBrowseFileController' => 'DiffusionController',
'DiffusionBrowseTableView' => 'DiffusionView',
'DiffusionChangeController' => 'DiffusionController',
'DiffusionCommentListView' => 'AphrontView',
'DiffusionCommentView' => 'AphrontView',
'DiffusionCommitChangeTableView' => 'DiffusionView',
'DiffusionCommitController' => 'DiffusionController',
'DiffusionContainsQuery' => 'DiffusionQuery',
'DiffusionController' => 'PhabricatorController',
'DiffusionDiffController' => 'DiffusionController',
'DiffusionEmptyResultView' => 'DiffusionView',
'DiffusionGitBranchQuery' => 'DiffusionBranchQuery',
'DiffusionGitBranchQueryTestCase' => 'PhabricatorTestCase',
'DiffusionGitBrowseQuery' => 'DiffusionBrowseQuery',
'DiffusionGitContainsQuery' => 'DiffusionContainsQuery',
'DiffusionGitDiffQuery' => 'DiffusionDiffQuery',
'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery',
'DiffusionGitHistoryQuery' => 'DiffusionHistoryQuery',
'DiffusionGitLastModifiedQuery' => 'DiffusionLastModifiedQuery',
'DiffusionGitRequest' => 'DiffusionRequest',
'DiffusionHistoryController' => 'DiffusionController',
'DiffusionHistoryTableView' => 'DiffusionView',
'DiffusionHomeController' => 'DiffusionController',
'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController',
'DiffusionLastModifiedController' => 'DiffusionController',
'DiffusionMercurialBranchQuery' => 'DiffusionBranchQuery',
'DiffusionMercurialBrowseQuery' => 'DiffusionBrowseQuery',
'DiffusionMercurialContainsQuery' => 'DiffusionContainsQuery',
'DiffusionMercurialDiffQuery' => 'DiffusionDiffQuery',
'DiffusionMercurialFileContentQuery' => 'DiffusionFileContentQuery',
'DiffusionMercurialHistoryQuery' => 'DiffusionHistoryQuery',
'DiffusionMercurialLastModifiedQuery' => 'DiffusionLastModifiedQuery',
'DiffusionMercurialRequest' => 'DiffusionRequest',
'DiffusionPathCompleteController' => 'DiffusionController',
'DiffusionPathQueryTestCase' => 'PhabricatorTestCase',
'DiffusionPathValidateController' => 'DiffusionController',
'DiffusionRepositoryController' => 'DiffusionController',
'DiffusionSVNContainsQuery' => 'DiffusionContainsQuery',
'DiffusionSvnBrowseQuery' => 'DiffusionBrowseQuery',
'DiffusionSvnDiffQuery' => 'DiffusionDiffQuery',
'DiffusionSvnFileContentQuery' => 'DiffusionFileContentQuery',
'DiffusionSvnHistoryQuery' => 'DiffusionHistoryQuery',
'DiffusionSvnLastModifiedQuery' => 'DiffusionLastModifiedQuery',
'DiffusionSvnRequest' => 'DiffusionRequest',
'DiffusionSymbolController' => 'DiffusionController',
+ 'DiffusionURITestCase' => 'ArcanistPhutilTestCase',
'DiffusionView' => 'AphrontView',
'DrydockAllocatorWorker' => 'PhabricatorWorker',
'DrydockCommandInterface' => 'DrydockInterface',
'DrydockController' => 'PhabricatorController',
'DrydockDAO' => 'PhabricatorLiskDAO',
'DrydockEC2HostBlueprint' => 'DrydockRemoteHostBlueprint',
'DrydockLease' => 'DrydockDAO',
'DrydockLeaseListController' => 'DrydockController',
'DrydockLeaseStatus' => 'DrydockConstants',
'DrydockLocalCommandInterface' => 'DrydockCommandInterface',
'DrydockLocalHostBlueprint' => 'DrydockBlueprint',
'DrydockRemoteHostBlueprint' => 'DrydockBlueprint',
'DrydockResource' => 'DrydockDAO',
'DrydockResourceAllocateController' => 'DrydockController',
'DrydockResourceListController' => 'DrydockController',
'DrydockResourceStatus' => 'DrydockConstants',
'DrydockSSHCommandInterface' => 'DrydockCommandInterface',
'HeraldAction' => 'HeraldDAO',
'HeraldAllRulesController' => 'HeraldController',
'HeraldApplyTranscript' => 'HeraldDAO',
'HeraldCommitAdapter' => 'HeraldObjectAdapter',
'HeraldCondition' => 'HeraldDAO',
'HeraldController' => 'PhabricatorController',
'HeraldDAO' => 'PhabricatorLiskDAO',
'HeraldDeleteController' => 'HeraldController',
'HeraldDifferentialRevisionAdapter' => 'HeraldObjectAdapter',
'HeraldDryRunAdapter' => 'HeraldObjectAdapter',
'HeraldHomeController' => 'HeraldController',
'HeraldNewController' => 'HeraldController',
'HeraldRule' => 'HeraldDAO',
'HeraldRuleController' => 'HeraldController',
'HeraldRuleEdit' => 'HeraldDAO',
'HeraldRuleEditHistoryController' => 'HeraldController',
'HeraldRuleEditHistoryView' => 'AphrontView',
'HeraldRuleListView' => 'AphrontView',
'HeraldTestConsoleController' => 'HeraldController',
'HeraldTranscript' => 'HeraldDAO',
'HeraldTranscriptController' => 'HeraldController',
'HeraldTranscriptListController' => 'HeraldController',
'JavelinReactorExample' => 'PhabricatorUIExample',
'JavelinViewExample' => 'PhabricatorUIExample',
'JavelinViewExampleServerView' => 'AphrontView',
'LiskIsolationTestCase' => 'PhabricatorTestCase',
'LiskIsolationTestDAO' => 'LiskDAO',
'ManiphestAction' => 'PhrictionConstants',
'ManiphestAuxiliaryFieldDefaultSpecification' => 'ManiphestAuxiliaryFieldSpecification',
'ManiphestBatchEditController' => 'ManiphestController',
'ManiphestController' => 'PhabricatorController',
'ManiphestDAO' => 'PhabricatorLiskDAO',
'ManiphestDefaultTaskExtensions' => 'ManiphestTaskExtensions',
'ManiphestExportController' => 'ManiphestController',
'ManiphestReplyHandler' => 'PhabricatorMailReplyHandler',
'ManiphestReportController' => 'ManiphestController',
'ManiphestTask' => 'ManiphestDAO',
'ManiphestTaskAuxiliaryStorage' => 'ManiphestDAO',
'ManiphestTaskDescriptionChangeController' => 'ManiphestController',
'ManiphestTaskDescriptionPreviewController' => 'ManiphestController',
'ManiphestTaskDetailController' => 'ManiphestController',
'ManiphestTaskEditController' => 'ManiphestController',
'ManiphestTaskListController' => 'ManiphestController',
'ManiphestTaskListView' => 'ManiphestView',
'ManiphestTaskOwner' => 'ManiphestConstants',
'ManiphestTaskPriority' => 'ManiphestConstants',
'ManiphestTaskProject' => 'ManiphestDAO',
'ManiphestTaskStatus' => 'ManiphestConstants',
'ManiphestTaskSubscriber' => 'ManiphestDAO',
'ManiphestTaskSummaryView' => 'ManiphestView',
'ManiphestTransaction' => 'ManiphestDAO',
'ManiphestTransactionDetailView' => 'ManiphestView',
'ManiphestTransactionListView' => 'ManiphestView',
'ManiphestTransactionPreviewController' => 'ManiphestController',
'ManiphestTransactionSaveController' => 'ManiphestController',
'ManiphestTransactionType' => 'ManiphestConstants',
'ManiphestView' => 'AphrontView',
'MetaMTANotificationType' => 'MetaMTAConstants',
'Phabricator404Controller' => 'PhabricatorController',
'PhabricatorAphlictTestPageController' => 'PhabricatorNotificationsController',
'PhabricatorAuditAddCommentController' => 'PhabricatorAuditController',
'PhabricatorAuditComment' => 'PhabricatorAuditDAO',
'PhabricatorAuditCommitListView' => 'AphrontView',
'PhabricatorAuditController' => 'PhabricatorController',
'PhabricatorAuditDAO' => 'PhabricatorLiskDAO',
'PhabricatorAuditInlineComment' => 'PhabricatorAuditDAO',
'PhabricatorAuditListController' => 'PhabricatorAuditController',
'PhabricatorAuditListView' => 'AphrontView',
'PhabricatorAuditPreviewController' => 'PhabricatorAuditController',
'PhabricatorAuditReplyHandler' => 'PhabricatorMailReplyHandler',
'PhabricatorAuthController' => 'PhabricatorController',
'PhabricatorCalendarBrowseController' => 'PhabricatorCalendarController',
'PhabricatorCalendarController' => 'PhabricatorController',
'PhabricatorChangesetResponse' => 'AphrontProxyResponse',
'PhabricatorChatLogChannelListController' => 'PhabricatorChatLogController',
'PhabricatorChatLogChannelLogController' => 'PhabricatorChatLogController',
'PhabricatorChatLogController' => 'PhabricatorController',
'PhabricatorChatLogDAO' => 'PhabricatorLiskDAO',
'PhabricatorChatLogEvent' => 'PhabricatorChatLogDAO',
'PhabricatorChatLogEventType' => 'PhabricatorChatLogConstants',
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO',
'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO',
'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
'PhabricatorConduitController' => 'PhabricatorController',
'PhabricatorConduitDAO' => 'PhabricatorLiskDAO',
'PhabricatorConduitLogController' => 'PhabricatorConduitController',
'PhabricatorConduitMethodCallLog' => 'PhabricatorConduitDAO',
'PhabricatorConduitTokenController' => 'PhabricatorConduitController',
'PhabricatorContentSourceView' => 'AphrontView',
'PhabricatorController' => 'AphrontController',
'PhabricatorCountdownController' => 'PhabricatorController',
'PhabricatorCountdownDAO' => 'PhabricatorLiskDAO',
'PhabricatorCountdownDeleteController' => 'PhabricatorCountdownController',
'PhabricatorCountdownEditController' => 'PhabricatorCountdownController',
'PhabricatorCountdownListController' => 'PhabricatorCountdownController',
'PhabricatorCountdownViewController' => 'PhabricatorCountdownController',
'PhabricatorDaemon' => 'PhutilDaemon',
'PhabricatorDaemonCombinedLogController' => 'PhabricatorDaemonController',
'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController',
'PhabricatorDaemonController' => 'PhabricatorController',
'PhabricatorDaemonDAO' => 'PhabricatorLiskDAO',
'PhabricatorDaemonLog' => 'PhabricatorDaemonDAO',
'PhabricatorDaemonLogEvent' => 'PhabricatorDaemonDAO',
'PhabricatorDaemonLogEventsView' => 'AphrontView',
'PhabricatorDaemonLogListController' => 'PhabricatorDaemonController',
'PhabricatorDaemonLogListView' => 'AphrontView',
'PhabricatorDaemonLogViewController' => 'PhabricatorDaemonController',
'PhabricatorDaemonTimelineConsoleController' => 'PhabricatorDaemonController',
'PhabricatorDaemonTimelineEventController' => 'PhabricatorDaemonController',
'PhabricatorDefaultFileStorageEngineSelector' => 'PhabricatorFileStorageEngineSelector',
'PhabricatorDefaultSearchEngineSelector' => 'PhabricatorSearchEngineSelector',
'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO',
'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryCategoryEditController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryCategoryViewController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryController' => 'PhabricatorController',
'PhabricatorDirectoryDAO' => 'PhabricatorLiskDAO',
'PhabricatorDirectoryEditController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryItem' => 'PhabricatorDirectoryDAO',
'PhabricatorDirectoryItemDeleteController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryItemEditController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryMainController' => 'PhabricatorDirectoryController',
'PhabricatorDisabledUserController' => 'PhabricatorAuthController',
'PhabricatorDraft' => 'PhabricatorDraftDAO',
'PhabricatorDraftDAO' => 'PhabricatorLiskDAO',
'PhabricatorEmailLoginController' => 'PhabricatorAuthController',
'PhabricatorEmailTokenController' => 'PhabricatorAuthController',
'PhabricatorEnvTestCase' => 'PhabricatorTestCase',
'PhabricatorEvent' => 'PhutilEvent',
'PhabricatorEventType' => 'PhutilEventType',
'PhabricatorFeedController' => 'PhabricatorController',
'PhabricatorFeedDAO' => 'PhabricatorLiskDAO',
'PhabricatorFeedPublicStreamController' => 'PhabricatorFeedController',
'PhabricatorFeedStoryAudit' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryData' => 'PhabricatorFeedDAO',
'PhabricatorFeedStoryDifferential' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryManiphest' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryPhriction' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryProject' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryReference' => 'PhabricatorFeedDAO',
'PhabricatorFeedStoryStatus' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryTypeConstants' => 'PhabricatorFeedConstants',
'PhabricatorFeedStoryUnknown' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryView' => 'PhabricatorFeedView',
'PhabricatorFeedView' => 'AphrontView',
'PhabricatorFile' => 'PhabricatorFileDAO',
'PhabricatorFileController' => 'PhabricatorController',
'PhabricatorFileDAO' => 'PhabricatorLiskDAO',
'PhabricatorFileDataController' => 'PhabricatorFileController',
'PhabricatorFileDeleteController' => 'PhabricatorFileController',
'PhabricatorFileDropUploadController' => 'PhabricatorFileController',
'PhabricatorFileImageMacro' => 'PhabricatorFileDAO',
'PhabricatorFileInfoController' => 'PhabricatorFileController',
'PhabricatorFileListController' => 'PhabricatorFileController',
'PhabricatorFileMacroDeleteController' => 'PhabricatorFileController',
'PhabricatorFileMacroEditController' => 'PhabricatorFileController',
'PhabricatorFileMacroListController' => 'PhabricatorFileController',
'PhabricatorFileProxyController' => 'PhabricatorFileController',
'PhabricatorFileProxyImage' => 'PhabricatorFileDAO',
'PhabricatorFileSideNavView' => 'AphrontView',
'PhabricatorFileStorageBlob' => 'PhabricatorFileDAO',
'PhabricatorFileTransformController' => 'PhabricatorFileController',
'PhabricatorFileUploadController' => 'PhabricatorFileController',
'PhabricatorFileUploadView' => 'AphrontView',
'PhabricatorGarbageCollectorDaemon' => 'PhabricatorDaemon',
'PhabricatorGoodForNothingWorker' => 'PhabricatorWorker',
'PhabricatorHelpController' => 'PhabricatorController',
'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController',
'PhabricatorIRCBot' => 'PhabricatorDaemon',
'PhabricatorIRCDifferentialNotificationHandler' => 'PhabricatorIRCHandler',
'PhabricatorIRCLogHandler' => 'PhabricatorIRCHandler',
'PhabricatorIRCMacroHandler' => 'PhabricatorIRCHandler',
'PhabricatorIRCObjectNameHandler' => 'PhabricatorIRCHandler',
'PhabricatorIRCProtocolHandler' => 'PhabricatorIRCHandler',
'PhabricatorIRCWhatsNewHandler' => 'PhabricatorIRCHandler',
'PhabricatorInfrastructureTestCase' => 'PhabricatorTestCase',
'PhabricatorInlineCommentController' => 'PhabricatorController',
'PhabricatorInlineSummaryView' => 'AphrontView',
'PhabricatorJavelinLinter' => 'ArcanistLinter',
'PhabricatorLintEngine' => 'PhutilLintEngine',
'PhabricatorLiskDAO' => 'LiskDAO',
'PhabricatorLocalDiskFileStorageEngine' => 'PhabricatorFileStorageEngine',
'PhabricatorLocalTimeTestCase' => 'PhabricatorTestCase',
'PhabricatorLoginController' => 'PhabricatorAuthController',
'PhabricatorLoginValidateController' => 'PhabricatorAuthController',
'PhabricatorLogoutController' => 'PhabricatorAuthController',
'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter',
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMetaMTAController' => 'PhabricatorController',
'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO',
'PhabricatorMetaMTAEmailBodyParserTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTAListController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTAMailingList' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAMailingListEditController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAMailingListsController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAReceiveController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAReceivedListController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTASendController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTASendGridReceiveController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAViewController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAWorker' => 'PhabricatorWorker',
'PhabricatorMySQLFileStorageEngine' => 'PhabricatorFileStorageEngine',
'PhabricatorNotificationsController' => 'PhabricatorController',
'PhabricatorOAuthClientAuthorization' => 'PhabricatorOAuthServerDAO',
'PhabricatorOAuthClientAuthorizationBaseController' => 'PhabricatorOAuthServerController',
'PhabricatorOAuthClientAuthorizationDeleteController' => 'PhabricatorOAuthClientAuthorizationBaseController',
'PhabricatorOAuthClientAuthorizationEditController' => 'PhabricatorOAuthClientAuthorizationBaseController',
'PhabricatorOAuthClientAuthorizationListController' => 'PhabricatorOAuthClientAuthorizationBaseController',
'PhabricatorOAuthClientBaseController' => 'PhabricatorOAuthServerController',
'PhabricatorOAuthClientDeleteController' => 'PhabricatorOAuthClientBaseController',
'PhabricatorOAuthClientEditController' => 'PhabricatorOAuthClientBaseController',
'PhabricatorOAuthClientListController' => 'PhabricatorOAuthClientBaseController',
'PhabricatorOAuthClientViewController' => 'PhabricatorOAuthClientBaseController',
'PhabricatorOAuthDefaultRegistrationController' => 'PhabricatorOAuthRegistrationController',
'PhabricatorOAuthDiagnosticsController' => 'PhabricatorAuthController',
'PhabricatorOAuthFailureView' => 'AphrontView',
'PhabricatorOAuthLoginController' => 'PhabricatorAuthController',
'PhabricatorOAuthProviderFacebook' => 'PhabricatorOAuthProvider',
'PhabricatorOAuthProviderGitHub' => 'PhabricatorOAuthProvider',
'PhabricatorOAuthProviderGoogle' => 'PhabricatorOAuthProvider',
'PhabricatorOAuthProviderPhabricator' => 'PhabricatorOAuthProvider',
'PhabricatorOAuthRegistrationController' => 'PhabricatorAuthController',
'PhabricatorOAuthResponse' => 'AphrontResponse',
'PhabricatorOAuthServerAccessToken' => 'PhabricatorOAuthServerDAO',
'PhabricatorOAuthServerAuthController' => 'PhabricatorAuthController',
'PhabricatorOAuthServerAuthorizationCode' => 'PhabricatorOAuthServerDAO',
'PhabricatorOAuthServerClient' => 'PhabricatorOAuthServerDAO',
'PhabricatorOAuthServerController' => 'PhabricatorController',
'PhabricatorOAuthServerDAO' => 'PhabricatorLiskDAO',
'PhabricatorOAuthServerTestCase' => 'PhabricatorTestCase',
'PhabricatorOAuthServerTestController' => 'PhabricatorOAuthServerController',
'PhabricatorOAuthServerTokenController' => 'PhabricatorAuthController',
'PhabricatorOAuthUnlinkController' => 'PhabricatorAuthController',
'PhabricatorObjectGraph' => 'AbstractDirectedGraph',
'PhabricatorObjectHandleStatus' => 'PhabricatorObjectHandleConstants',
'PhabricatorOwnersController' => 'PhabricatorController',
'PhabricatorOwnersDAO' => 'PhabricatorLiskDAO',
'PhabricatorOwnersDeleteController' => 'PhabricatorOwnersController',
'PhabricatorOwnersDetailController' => 'PhabricatorOwnersController',
'PhabricatorOwnersEditController' => 'PhabricatorOwnersController',
'PhabricatorOwnersListController' => 'PhabricatorOwnersController',
'PhabricatorOwnersOwner' => 'PhabricatorOwnersDAO',
'PhabricatorOwnersPackage' => 'PhabricatorOwnersDAO',
'PhabricatorOwnersPath' => 'PhabricatorOwnersDAO',
'PhabricatorPHID' => 'PhabricatorPHIDDAO',
'PhabricatorPHIDController' => 'PhabricatorController',
'PhabricatorPHIDDAO' => 'PhabricatorLiskDAO',
'PhabricatorPHIDLookupController' => 'PhabricatorPHIDController',
'PhabricatorPaste' => 'PhabricatorPasteDAO',
'PhabricatorPasteController' => 'PhabricatorController',
'PhabricatorPasteDAO' => 'PhabricatorLiskDAO',
'PhabricatorPasteListController' => 'PhabricatorPasteController',
'PhabricatorPasteViewController' => 'PhabricatorPasteController',
'PhabricatorPeopleController' => 'PhabricatorController',
'PhabricatorPeopleEditController' => 'PhabricatorPeopleController',
'PhabricatorPeopleListController' => 'PhabricatorPeopleController',
'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController',
'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController',
'PhabricatorProfileHeaderView' => 'AphrontView',
'PhabricatorProject' => 'PhabricatorProjectDAO',
'PhabricatorProjectAffiliation' => 'PhabricatorProjectDAO',
'PhabricatorProjectController' => 'PhabricatorController',
'PhabricatorProjectCreateController' => 'PhabricatorProjectController',
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
'PhabricatorProjectListController' => 'PhabricatorProjectController',
'PhabricatorProjectProfile' => 'PhabricatorProjectDAO',
'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
'PhabricatorProjectProfileEditController' => 'PhabricatorProjectController',
'PhabricatorProjectSubproject' => 'PhabricatorProjectDAO',
'PhabricatorProjectTransaction' => 'PhabricatorProjectDAO',
'PhabricatorProjectTransactionType' => 'PhabricatorProjectConstants',
'PhabricatorProjectUpdateController' => 'PhabricatorProjectController',
'PhabricatorRedirectController' => 'PhabricatorController',
'PhabricatorRefreshCSRFController' => 'PhabricatorAuthController',
'PhabricatorRemarkupRuleDifferential' => 'PhabricatorRemarkupRuleObjectName',
'PhabricatorRemarkupRuleDifferentialHandle' => 'PhabricatorRemarkupRuleObjectHandle',
'PhabricatorRemarkupRuleDiffusion' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleEmbedFile' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleImageMacro' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleManiphest' => 'PhabricatorRemarkupRuleObjectName',
'PhabricatorRemarkupRuleManiphestHandle' => 'PhabricatorRemarkupRuleObjectHandle',
'PhabricatorRemarkupRuleMention' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleObjectHandle' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleObjectName' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRulePaste' => 'PhabricatorRemarkupRuleObjectName',
'PhabricatorRemarkupRulePhriction' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleProxyImage' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleYoutube' => 'PhutilRemarkupRule',
'PhabricatorRepository' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryArcanistProject' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryArcanistProjectEditController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryAuditRequest' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryCommit' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryCommitDiscoveryDaemon' => 'PhabricatorRepositoryDaemon',
'PhabricatorRepositoryCommitHeraldWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitOwnersWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitParserWorker' => 'PhabricatorWorker',
'PhabricatorRepositoryCommitTaskDaemon' => 'PhabricatorRepositoryDaemon',
'PhabricatorRepositoryController' => 'PhabricatorController',
'PhabricatorRepositoryCreateController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO',
'PhabricatorRepositoryDaemon' => 'PhabricatorDaemon',
'PhabricatorRepositoryDefaultCommitMessageDetailParser' => 'PhabricatorRepositoryCommitMessageDetailParser',
'PhabricatorRepositoryDeleteController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryEditController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
'PhabricatorRepositoryGitCommitDiscoveryDaemonTestCase' => 'PhabricatorTestCase',
'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorRepositoryGitFetchDaemon' => 'PhabricatorRepositoryPullLocalDaemon',
'PhabricatorRepositoryListController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
'PhabricatorRepositoryMercurialCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorRepositoryMercurialPullDaemon' => 'PhabricatorRepositoryPullLocalDaemon',
'PhabricatorRepositoryPullLocalDaemon' => 'PhabricatorRepositoryDaemon',
'PhabricatorRepositoryShortcut' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorRepositorySymbol' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryTestCase' => 'PhabricatorTestCase',
'PhabricatorS3FileStorageEngine' => 'PhabricatorFileStorageEngine',
'PhabricatorSearchAttachController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchBaseController' => 'PhabricatorController',
'PhabricatorSearchCommitIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorSearchController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchDAO' => 'PhabricatorLiskDAO',
'PhabricatorSearchDifferentialIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorSearchDocument' => 'PhabricatorSearchDAO',
'PhabricatorSearchDocumentField' => 'PhabricatorSearchDAO',
'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO',
'PhabricatorSearchEngineMySQL' => 'PhabricatorSearchEngine',
'PhabricatorSearchIndexController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchManiphestIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorSearchPhrictionIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorSearchQuery' => 'PhabricatorSearchDAO',
'PhabricatorSearchResultView' => 'AphrontView',
'PhabricatorSearchSelectController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchUserIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO',
'PhabricatorSlowvoteComment' => 'PhabricatorSlowvoteDAO',
'PhabricatorSlowvoteController' => 'PhabricatorController',
'PhabricatorSlowvoteCreateController' => 'PhabricatorSlowvoteController',
'PhabricatorSlowvoteDAO' => 'PhabricatorLiskDAO',
'PhabricatorSlowvoteListController' => 'PhabricatorSlowvoteController',
'PhabricatorSlowvoteOption' => 'PhabricatorSlowvoteDAO',
'PhabricatorSlowvotePoll' => 'PhabricatorSlowvoteDAO',
'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController',
'PhabricatorSortTableExample' => 'PhabricatorUIExample',
'PhabricatorStandardPageView' => 'AphrontPageView',
'PhabricatorStatusController' => 'PhabricatorController',
'PhabricatorSymbolNameLinter' => 'ArcanistXHPASTLintNamingHook',
'PhabricatorTaskmasterDaemon' => 'PhabricatorDaemon',
'PhabricatorTestCase' => 'ArcanistPhutilTestCase',
'PhabricatorTimelineCursor' => 'PhabricatorTimelineDAO',
'PhabricatorTimelineDAO' => 'PhabricatorLiskDAO',
'PhabricatorTimelineEvent' => 'PhabricatorTimelineDAO',
'PhabricatorTimelineEventData' => 'PhabricatorTimelineDAO',
'PhabricatorTimer' => 'PhabricatorCountdownDAO',
'PhabricatorTransactionView' => 'AphrontView',
'PhabricatorTransformedFile' => 'PhabricatorFileDAO',
'PhabricatorTrivialTestCase' => 'PhabricatorTestCase',
'PhabricatorTypeaheadCommonDatasourceController' => 'PhabricatorTypeaheadDatasourceController',
'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController',
'PhabricatorUIExampleController' => 'PhabricatorController',
'PhabricatorUIExampleRenderController' => 'PhabricatorUIExampleController',
'PhabricatorUIListFilterExample' => 'PhabricatorUIExample',
'PhabricatorUIPagerExample' => 'PhabricatorUIExample',
'PhabricatorUITooltipExample' => 'PhabricatorUIExample',
'PhabricatorUser' => 'PhabricatorUserDAO',
'PhabricatorUserAccountSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserConduitSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserDAO' => 'PhabricatorLiskDAO',
'PhabricatorUserEmailPreferenceSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserEmailSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserLog' => 'PhabricatorUserDAO',
'PhabricatorUserOAuthInfo' => 'PhabricatorUserDAO',
'PhabricatorUserOAuthSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserPasswordSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserPreferenceSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserPreferences' => 'PhabricatorUserDAO',
'PhabricatorUserProfile' => 'PhabricatorUserDAO',
'PhabricatorUserProfileSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserSSHKey' => 'PhabricatorUserDAO',
'PhabricatorUserSSHKeysSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserSearchSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserSettingsController' => 'PhabricatorPeopleController',
'PhabricatorUserSettingsPanelController' => 'PhabricatorPeopleController',
'PhabricatorUserTestCase' => 'PhabricatorTestCase',
'PhabricatorWorkerDAO' => 'PhabricatorLiskDAO',
'PhabricatorWorkerTask' => 'PhabricatorWorkerDAO',
'PhabricatorWorkerTaskData' => 'PhabricatorWorkerDAO',
'PhabricatorWorkerTaskDetailController' => 'PhabricatorDaemonController',
'PhabricatorWorkerTaskUpdateController' => 'PhabricatorDaemonController',
'PhabricatorXHPASTViewController' => 'PhabricatorController',
'PhabricatorXHPASTViewDAO' => 'PhabricatorLiskDAO',
'PhabricatorXHPASTViewFrameController' => 'PhabricatorXHPASTViewController',
'PhabricatorXHPASTViewFramesetController' => 'PhabricatorXHPASTViewController',
'PhabricatorXHPASTViewInputController' => 'PhabricatorXHPASTViewPanelController',
'PhabricatorXHPASTViewPanelController' => 'PhabricatorXHPASTViewController',
'PhabricatorXHPASTViewParseTree' => 'PhabricatorXHPASTViewDAO',
'PhabricatorXHPASTViewRunController' => 'PhabricatorXHPASTViewController',
'PhabricatorXHPASTViewStreamController' => 'PhabricatorXHPASTViewPanelController',
'PhabricatorXHPASTViewTreeController' => 'PhabricatorXHPASTViewPanelController',
'PhabricatorXHProfController' => 'PhabricatorController',
'PhabricatorXHProfProfileController' => 'PhabricatorXHProfController',
'PhabricatorXHProfProfileSymbolView' => 'PhabricatorXHProfProfileView',
'PhabricatorXHProfProfileTopLevelView' => 'PhabricatorXHProfProfileView',
'PhabricatorXHProfProfileView' => 'AphrontView',
'PhrictionActionConstants' => 'PhrictionConstants',
'PhrictionChangeType' => 'PhrictionConstants',
'PhrictionContent' => 'PhrictionDAO',
'PhrictionController' => 'PhabricatorController',
'PhrictionDAO' => 'PhabricatorLiskDAO',
'PhrictionDeleteController' => 'PhrictionController',
'PhrictionDiffController' => 'PhrictionController',
'PhrictionDocument' => 'PhrictionDAO',
'PhrictionDocumentController' => 'PhrictionController',
'PhrictionDocumentPreviewController' => 'PhrictionController',
'PhrictionDocumentStatus' => 'PhrictionConstants',
'PhrictionDocumentTestCase' => 'PhabricatorTestCase',
'PhrictionEditController' => 'PhrictionController',
'PhrictionHistoryController' => 'PhrictionController',
'PhrictionListController' => 'PhrictionController',
'QueryFormattingTestCase' => 'PhabricatorTestCase',
),
'requires_interface' =>
array(
'DifferentialInlineComment' =>
array(
0 => 'PhabricatorInlineCommentInterface',
),
'PhabricatorAuditInlineComment' =>
array(
0 => 'PhabricatorInlineCommentInterface',
),
),
));
diff --git a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
index 25b2e03211..113f9b824f 100644
--- a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
+++ b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
@@ -1,627 +1,610 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @group aphront
*/
class AphrontDefaultApplicationConfiguration
extends AphrontApplicationConfiguration {
public function __construct() {
}
public function getApplicationName() {
return 'aphront-default';
}
public function getURIMap() {
return $this->getResourceURIMapRules() + array(
'/(?:(?P<filter>jump)/)?' =>
'PhabricatorDirectoryMainController',
'/(?:(?P<filter>feed)/)' => array(
'public/' => 'PhabricatorFeedPublicStreamController',
'(?:(?P<subfilter>[^/]+)/)?' =>
'PhabricatorDirectoryMainController',
),
'/directory/' => array(
'(?P<id>\d+)/'
=> 'PhabricatorDirectoryCategoryViewController',
'edit/'
=> 'PhabricatorDirectoryEditController',
'item/edit/(?:(?P<id>\d+)/)?'
=> 'PhabricatorDirectoryItemEditController',
'item/delete/(?P<id>\d+)/'
=> 'PhabricatorDirectoryItemDeleteController',
'category/edit/(?:(?P<id>\d+)/)?'
=> 'PhabricatorDirectoryCategoryEditController',
'category/delete/(?P<id>\d+)/'
=> 'PhabricatorDirectoryCategoryDeleteController',
),
'/file/' => array(
'' => 'PhabricatorFileListController',
'filter/(?P<filter>\w+)/' => 'PhabricatorFileListController',
'upload/' => 'PhabricatorFileUploadController',
'dropupload/' => 'PhabricatorFileDropUploadController',
'delete/(?P<id>\d+)/' => 'PhabricatorFileDeleteController',
'info/(?P<phid>[^/]+)/' => 'PhabricatorFileInfoController',
'data/(?P<key>[^/]+)/(?P<phid>[^/]+)/.*'
=> 'PhabricatorFileDataController',
// TODO: This is a deprecated version of /data/. Remove it after
// old links have had a chance to rot.
'alt/(?P<key>[^/]+)/(?P<phid>[^/]+)/'
=> 'PhabricatorFileDataController',
'macro/' => array(
'' => 'PhabricatorFileMacroListController',
'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorFileMacroEditController',
'delete/(?P<id>\d+)/' => 'PhabricatorFileMacroDeleteController',
),
'proxy/' => 'PhabricatorFileProxyController',
'xform/(?P<transform>[^/]+)/(?P<phid>[^/]+)/'
=> 'PhabricatorFileTransformController',
),
'/phid/' => array(
'' => 'PhabricatorPHIDLookupController',
),
'/people/' => array(
'' => 'PhabricatorPeopleListController',
'logs/' => 'PhabricatorPeopleLogsController',
'edit/(?:(?P<id>\d+)/(?:(?P<view>\w+)/)?)?'
=> 'PhabricatorPeopleEditController',
),
'/p/(?P<username>\w+)/(?:(?P<page>\w+)/)?'
=> 'PhabricatorPeopleProfileController',
'/conduit/' => array(
'' => 'PhabricatorConduitConsoleController',
'method/(?P<method>[^/]+)/' => 'PhabricatorConduitConsoleController',
'log/' => 'PhabricatorConduitLogController',
'log/view/(?P<view>[^/]+)/' => 'PhabricatorConduitLogController',
'token/' => 'PhabricatorConduitTokenController',
),
'/api/(?P<method>[^/]+)' => 'PhabricatorConduitAPIController',
'/D(?P<id>\d+)' => 'DifferentialRevisionViewController',
'/differential/' => array(
'' => 'DifferentialRevisionListController',
'filter/(?P<filter>\w+)/(?:(?P<username>\w+)/)?' =>
'DifferentialRevisionListController',
'stats/(?P<filter>\w+)/' => 'DifferentialRevisionStatsController',
'diff/' => array(
'(?P<id>\d+)/' => 'DifferentialDiffViewController',
'create/' => 'DifferentialDiffCreateController',
),
'changeset/' => 'DifferentialChangesetViewController',
'revision/edit/(?:(?P<id>\d+)/)?'
=> 'DifferentialRevisionEditController',
'comment/' => array(
'preview/(?P<id>\d+)/' => 'DifferentialCommentPreviewController',
'save/' => 'DifferentialCommentSaveController',
'inline/' => array(
'preview/(?P<id>\d+)/' =>
'DifferentialInlineCommentPreviewController',
'edit/(?P<id>\d+)/' => 'DifferentialInlineCommentEditController',
),
),
'subscribe/(?P<action>add|rem)/(?P<id>\d+)/'
=> 'DifferentialSubscribeController',
),
'/typeahead/' => array(
'common/(?P<type>\w+)/'
=> 'PhabricatorTypeaheadCommonDatasourceController',
),
'/mail/' => array(
'' => 'PhabricatorMetaMTAListController',
'send/' => 'PhabricatorMetaMTASendController',
'view/(?P<id>\d+)/' => 'PhabricatorMetaMTAViewController',
'lists/' => 'PhabricatorMetaMTAMailingListsController',
'lists/edit/(?:(?P<id>\d+)/)?'
=> 'PhabricatorMetaMTAMailingListEditController',
'receive/' => 'PhabricatorMetaMTAReceiveController',
'received/' => 'PhabricatorMetaMTAReceivedListController',
'sendgrid/' => 'PhabricatorMetaMTASendGridReceiveController',
),
'/login/' => array(
'' => 'PhabricatorLoginController',
'email/' => 'PhabricatorEmailLoginController',
'etoken/(?P<token>\w+)/' => 'PhabricatorEmailTokenController',
'refresh/' => 'PhabricatorRefreshCSRFController',
'validate/' => 'PhabricatorLoginValidateController',
),
'/logout/' => 'PhabricatorLogoutController',
'/oauth/' => array(
'(?P<provider>\w+)/' => array(
'login/' => 'PhabricatorOAuthLoginController',
'diagnose/' => 'PhabricatorOAuthDiagnosticsController',
'unlink/' => 'PhabricatorOAuthUnlinkController',
),
),
'/oauthserver/' => array(
'auth/' => 'PhabricatorOAuthServerAuthController',
'test/' => 'PhabricatorOAuthServerTestController',
'token/' => 'PhabricatorOAuthServerTokenController',
'clientauthorization/' => array(
'' => 'PhabricatorOAuthClientAuthorizationListController',
'delete/(?P<phid>[^/]+)/' =>
'PhabricatorOAuthClientAuthorizationDeleteController',
'edit/(?P<phid>[^/]+)/' =>
'PhabricatorOAuthClientAuthorizationEditController',
),
'client/' => array(
'' => 'PhabricatorOAuthClientListController',
'create/' => 'PhabricatorOAuthClientEditController',
'delete/(?P<phid>[^/]+)/' => 'PhabricatorOAuthClientDeleteController',
'edit/(?P<phid>[^/]+)/' => 'PhabricatorOAuthClientEditController',
'view/(?P<phid>[^/]+)/' => 'PhabricatorOAuthClientViewController',
),
),
'/xhprof/' => array(
'profile/(?P<phid>[^/]+)/' => 'PhabricatorXHProfProfileController',
),
'/~/' => 'DarkConsoleController',
'/settings/' => array(
'(?:page/(?P<page>[^/]+)/)?' => 'PhabricatorUserSettingsController',
),
'/maniphest/' => array(
'' => 'ManiphestTaskListController',
'view/(?P<view>\w+)/' => 'ManiphestTaskListController',
'report/(?:(?P<view>\w+)/)?' => 'ManiphestReportController',
'batch/' => 'ManiphestBatchEditController',
'task/' => array(
'create/' => 'ManiphestTaskEditController',
'edit/(?P<id>\d+)/' => 'ManiphestTaskEditController',
'descriptionchange/(?:(?P<id>\d+)/)?' =>
'ManiphestTaskDescriptionChangeController',
'descriptionpreview/' =>
'ManiphestTaskDescriptionPreviewController',
),
'transaction/' => array(
'save/' => 'ManiphestTransactionSaveController',
'preview/(?P<id>\d+)/' => 'ManiphestTransactionPreviewController',
),
'export/(?P<key>[^/]+)/' => 'ManiphestExportController',
),
'/T(?P<id>\d+)' => 'ManiphestTaskDetailController',
'/repository/' => array(
'' => 'PhabricatorRepositoryListController',
'create/' => 'PhabricatorRepositoryCreateController',
'edit/(?P<id>\d+)/(?:(?P<view>\w+)?/)?' =>
'PhabricatorRepositoryEditController',
'delete/(?P<id>\d+)/' => 'PhabricatorRepositoryDeleteController',
'project/(?P<id>\d+)/' =>
'PhabricatorRepositoryArcanistProjectEditController',
),
'/search/' => array(
'' => 'PhabricatorSearchController',
'(?P<key>[^/]+)/' => 'PhabricatorSearchController',
'attach/(?P<phid>[^/]+)/(?P<type>\w+)/(?:(?P<action>\w+)/)?'
=> 'PhabricatorSearchAttachController',
'select/(?P<type>\w+)/'
=> 'PhabricatorSearchSelectController',
'index/(?P<phid>[^/]+)/' => 'PhabricatorSearchIndexController',
),
'/project/' => array(
'' => 'PhabricatorProjectListController',
'filter/(?P<filter>[^/]+)/' => 'PhabricatorProjectListController',
'edit/(?P<id>\d+)/' => 'PhabricatorProjectProfileEditController',
'view/(?P<id>\d+)/(?:(?P<page>\w+)/)?'
=> 'PhabricatorProjectProfileController',
'create/' => 'PhabricatorProjectCreateController',
'update/(?P<id>\d+)/(?P<action>[^/]+)/'
=> 'PhabricatorProjectUpdateController',
),
'/r(?P<callsign>[A-Z]+)(?P<commit>[a-z0-9]+)'
=> 'DiffusionCommitController',
'/diffusion/' => array(
'' => 'DiffusionHomeController',
'(?P<callsign>[A-Z]+)/' => array(
'' => 'DiffusionRepositoryController',
- 'repository/'.
- '(?P<path>[^/]+)/'
- => 'DiffusionRepositoryController',
- 'change/'.
- '(?P<path>.*?)'.
- '(?:[;](?P<commit>[a-z0-9]+))?'
- => 'DiffusionChangeController',
- 'history/'.
- '(?P<path>.*?)'.
- '(?:[;](?P<commit>[a-z0-9]+))?'
- => 'DiffusionHistoryController',
- 'browse/'.
- '(?P<path>.*?)'.
- '(?:[;](?P<commit>[a-z0-9]+))?'.
- '(?:[$](?P<line>\d+(?:-\d+)?))?'
- => 'DiffusionBrowseController',
- 'diff/'.
- '(?P<path>.*?)'.
- '(?:[;](?P<commit>[a-z0-9]+))?'
- => 'DiffusionDiffController',
- 'lastmodified/'.
- '(?P<path>.*?)'.
- '(?:[;](?P<commit>[a-z0-9]+))?'
- => 'DiffusionLastModifiedController',
+
+ 'repository/(?P<dblob>.*)' => 'DiffusionRepositoryController',
+ 'change/(?P<dblob>.*)' => 'DiffusionChangeController',
+ 'history/(?P<dblob>.*)' => 'DiffusionHistoryController',
+ 'browse/(?P<dblob>.*)' => 'DiffusionBrowseController',
+ 'lastmodified/(?P<dblob>.*)' => 'DiffusionLastModifiedController',
+ 'diff/' => 'DiffusionDiffController',
),
'inline/(?P<phid>[^/]+)/' => 'DiffusionInlineCommentController',
'services/' => array(
'path/' => array(
'complete/' => 'DiffusionPathCompleteController',
'validate/' => 'DiffusionPathValidateController',
),
),
'symbol/(?P<name>[^/]+)/' => 'DiffusionSymbolController',
),
'/daemon/' => array(
'task/(?P<id>\d+)/' => 'PhabricatorWorkerTaskDetailController',
'task/(?P<id>\d+)/(?P<action>[^/]+)/'
=> 'PhabricatorWorkerTaskUpdateController',
'log/' => array(
'' => 'PhabricatorDaemonLogListController',
'combined/' => 'PhabricatorDaemonCombinedLogController',
'(?P<id>\d+)/' => 'PhabricatorDaemonLogViewController',
),
'timeline/' => 'PhabricatorDaemonTimelineConsoleController',
'timeline/(?P<id>\d+)/' => 'PhabricatorDaemonTimelineEventController',
'' => 'PhabricatorDaemonConsoleController',
),
'/herald/' => array(
'' => 'HeraldHomeController',
'view/(?P<view>[^/]+)/' => array(
'' => 'HeraldHomeController',
'(?P<global>global)/' => 'HeraldHomeController'
),
'new/(?:(?P<type>[^/]+)/)?' => 'HeraldNewController',
'rule/(?:(?P<id>\d+)/)?' => 'HeraldRuleController',
'history/(?P<id>\d+)/' => 'HeraldRuleEditHistoryController',
'delete/(?P<id>\d+)/' => 'HeraldDeleteController',
'test/' => 'HeraldTestConsoleController',
'all/' => array(
'' => 'HeraldAllRulesController',
'view/(?P<view>[^/]+)/' => 'HeraldAllRulesController',
),
'transcript/' => 'HeraldTranscriptListController',
'transcript/(?P<id>\d+)/(?:(?P<filter>\w+)/)?'
=> 'HeraldTranscriptController',
),
'/uiexample/' => array(
'' => 'PhabricatorUIExampleRenderController',
'view/(?P<class>[^/]+)/' => 'PhabricatorUIExampleRenderController',
),
'/owners/' => array(
'' => 'PhabricatorOwnersListController',
'view/(?P<view>[^/]+)/' => 'PhabricatorOwnersListController',
'edit/(?P<id>\d+)/' => 'PhabricatorOwnersEditController',
'new/' => 'PhabricatorOwnersEditController',
'package/(?P<id>\d+)/' => 'PhabricatorOwnersDetailController',
'delete/(?P<id>\d+)/' => 'PhabricatorOwnersDeleteController',
),
'/audit/' => array(
'' => 'PhabricatorAuditListController',
'view/(?P<filter>[^/]+)/(?:(?P<name>[^/]+)/)?'
=> 'PhabricatorAuditListController',
'addcomment/' => 'PhabricatorAuditAddCommentController',
'preview/(?P<id>\d+)/' => 'PhabricatorAuditPreviewController',
),
'/xhpast/' => array(
'' => 'PhabricatorXHPASTViewRunController',
'view/(?P<id>\d+)/'
=> 'PhabricatorXHPASTViewFrameController',
'frameset/(?P<id>\d+)/'
=> 'PhabricatorXHPASTViewFramesetController',
'input/(?P<id>\d+)/'
=> 'PhabricatorXHPASTViewInputController',
'tree/(?P<id>\d+)/'
=> 'PhabricatorXHPASTViewTreeController',
'stream/(?P<id>\d+)/'
=> 'PhabricatorXHPASTViewStreamController',
),
'/status/' => 'PhabricatorStatusController',
'/paste/' => array(
'' => 'PhabricatorPasteListController',
'filter/(?P<filter>\w+)/' => 'PhabricatorPasteListController',
),
'/P(?P<id>\d+)' => 'PhabricatorPasteViewController',
'/help/' => array(
'keyboardshortcut/' => 'PhabricatorHelpKeyboardShortcutController',
),
'/countdown/' => array(
''
=> 'PhabricatorCountdownListController',
'(?P<id>\d+)/'
=> 'PhabricatorCountdownViewController',
'edit/(?:(?P<id>\d+)/)?'
=> 'PhabricatorCountdownEditController',
'delete/(?P<id>\d+)/'
=> 'PhabricatorCountdownDeleteController'
),
'/V(?P<id>\d+)' => 'PhabricatorSlowvotePollController',
'/vote/' => array(
'(?:view/(?P<view>\w+)/)?' => 'PhabricatorSlowvoteListController',
'create/' => 'PhabricatorSlowvoteCreateController',
),
// Match "/w/" with slug "/".
'/w(?P<slug>/)' => 'PhrictionDocumentController',
// Match "/w/x/y/z/" with slug "x/y/z/".
'/w/(?P<slug>.+/)' => 'PhrictionDocumentController',
'/phriction/' => array(
'' => 'PhrictionListController',
'list/(?P<view>[^/]+)/' => 'PhrictionListController',
'history(?P<slug>/)' => 'PhrictionHistoryController',
'history/(?P<slug>.+/)' => 'PhrictionHistoryController',
'edit/(?:(?P<id>\d+)/)?' => 'PhrictionEditController',
'delete/(?P<id>\d+)/' => 'PhrictionDeleteController',
'preview/' => 'PhrictionDocumentPreviewController',
'diff/(?P<id>\d+)/' => 'PhrictionDiffController',
),
'/calendar/' => array(
'' => 'PhabricatorCalendarBrowseController',
),
'/drydock/' => array(
'' => 'DrydockResourceListController',
'resource/' => 'DrydockResourceListController',
'resource/allocate/' => 'DrydockResourceAllocateController',
'host/' => array(
'' => 'DrydockHostListController',
'edit/' => 'DrydockHostEditController',
'edit/(?P<id>\d+)/' => 'DrydockhostEditController',
),
'lease/' => 'DrydockLeaseListController',
),
'/chatlog/' => array(
'' =>
'PhabricatorChatLogChannelListController',
'channel/(?P<channel>[^/]+)/' =>
'PhabricatorChatLogChannelLogController',
),
'/aphlict/' => 'PhabricatorAphlictTestPageController',
);
}
protected function getResourceURIMapRules() {
return array(
'/res/' => array(
'(?P<package>pkg/)?(?P<hash>[a-f0-9]{8})/(?P<path>.+\.(?:css|js))'
=> 'CelerityResourceController',
),
);
}
public function buildRequest() {
$request = new AphrontRequest($this->getHost(), $this->getPath());
$request->setRequestData($_GET + $_POST);
$request->setApplicationConfiguration($this);
return $request;
}
public function handleException(Exception $ex) {
// Always log the unhandled exception.
phlog($ex);
$class = phutil_escape_html(get_class($ex));
$message = phutil_escape_html($ex->getMessage());
if (PhabricatorEnv::getEnvConfig('phabricator.show-stack-traces')) {
$trace = $this->renderStackTrace($ex->getTrace());
} else {
$trace = null;
}
$content =
'<div class="aphront-unhandled-exception">'.
'<div class="exception-message">'.$message.'</div>'.
$trace.
'</div>';
$user = $this->getRequest()->getUser();
if (!$user) {
// If we hit an exception very early, we won't have a user.
$user = new PhabricatorUser();
}
$dialog = new AphrontDialogView();
$dialog
->setTitle('Unhandled Exception ("'.$class.'")')
->setClass('aphront-exception-dialog')
->setUser($user)
->appendChild($content);
if ($this->getRequest()->isAjax()) {
$dialog->addCancelButton('/', 'Close');
}
$response = new AphrontDialogResponse();
$response->setDialog($dialog);
return $response;
}
public function willSendResponse(AphrontResponse $response) {
$request = $this->getRequest();
$response->setRequest($request);
if ($response instanceof AphrontDialogResponse) {
if (!$request->isAjax()) {
$view = new PhabricatorStandardPageView();
$view->setRequest($request);
$view->appendChild(
'<div style="padding: 2em 0;">'.
$response->buildResponseString().
'</div>');
$response = new AphrontWebpageResponse();
$response->setContent($view->render());
return $response;
} else {
return id(new AphrontAjaxResponse())
->setContent(array(
'dialog' => $response->buildResponseString(),
));
}
} else if ($response instanceof AphrontRedirectResponse) {
if ($request->isAjax()) {
return id(new AphrontAjaxResponse())
->setContent(
array(
'redirect' => $response->getURI(),
));
}
}
return $response;
}
public function build404Controller() {
return array(new Phabricator404Controller($this->getRequest()), array());
}
public function buildRedirectController($uri) {
return array(
new PhabricatorRedirectController($this->getRequest()),
array(
'uri' => $uri,
));
}
private function renderStackTrace($trace) {
$libraries = PhutilBootloader::getInstance()->getAllLibraries();
// TODO: Make this configurable?
$host = 'https://secure.phabricator.com';
$browse = array(
'arcanist' =>
$host.'/diffusion/ARC/browse/origin:master/src/',
'phutil' =>
$host.'/diffusion/PHU/browse/origin:master/src/',
'phabricator' =>
$host.'/diffusion/P/browse/origin:master/src/',
);
$rows = array();
$depth = count($trace);
foreach ($trace as $part) {
$lib = null;
$file = idx($part, 'file');
$relative = $file;
foreach ($libraries as $library) {
$root = phutil_get_library_root($library);
if (Filesystem::isDescendant($file, $root)) {
$lib = $library;
$relative = Filesystem::readablePath($file, $root);
break;
}
}
$where = '';
if (isset($part['class'])) {
$where .= $part['class'].'::';
}
if (isset($part['function'])) {
$where .= $part['function'].'()';
}
if ($file) {
if (isset($browse[$lib])) {
$file_name = phutil_render_tag(
'a',
array(
'href' => $browse[$lib].$relative.'$'.$part['line'],
'title' => $file,
'target' => '_blank',
),
phutil_escape_html($relative));
} else {
$file_name = phutil_render_tag(
'span',
array(
'title' => $file,
),
phutil_escape_html($relative));
}
$file_name = $file_name.' : '.(int)$part['line'];
} else {
$file_name = '<em>(Internal)</em>';
}
$rows[] = array(
$depth--,
phutil_escape_html($lib),
$file_name,
phutil_escape_html($where),
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
'Depth',
'Library',
'File',
'Where',
));
$table->setColumnClasses(
array(
'n',
'',
'',
'wide',
));
return
'<div class="exception-trace">'.
'<div class="exception-trace-header">Stack Trace</div>'.
$table->render().
'</div>';
}
}
diff --git a/src/applications/conduit/method/diffusion/getrecentcommitsbypath/ConduitAPI_diffusion_getrecentcommitsbypath_Method.php b/src/applications/conduit/method/diffusion/getrecentcommitsbypath/ConduitAPI_diffusion_getrecentcommitsbypath_Method.php
index b409c0f2c3..c46c49ef74 100644
--- a/src/applications/conduit/method/diffusion/getrecentcommitsbypath/ConduitAPI_diffusion_getrecentcommitsbypath_Method.php
+++ b/src/applications/conduit/method/diffusion/getrecentcommitsbypath/ConduitAPI_diffusion_getrecentcommitsbypath_Method.php
@@ -1,67 +1,67 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @group conduit
*/
final class ConduitAPI_diffusion_getrecentcommitsbypath_Method
extends ConduitAPIMethod {
const RESULT_LIMIT = 10;
public function getMethodDescription() {
return "Get commit identifiers for recent commits affecting a given path.";
}
public function defineParamTypes() {
return array(
'callsign' => 'required string',
'path' => 'required string',
);
}
public function defineReturnType() {
return 'nonempty list<string>';
}
public function defineErrorTypes() {
return array(
);
}
protected function execute(ConduitAPIRequest $request) {
- $results = array();
+ $drequest = DiffusionRequest::newFromDictionary(
+ array(
+ 'callsign' => $request->getValue('callsign'),
+ 'path' => $request->getValue('path'),
+ ));
- $history = DiffusionHistoryQuery::newFromDiffusionRequest(
- DiffusionRequest::newFromAphrontRequestDictionary(
- $request->getAllParameters()
- )
- )
+ $history = DiffusionHistoryQuery::newFromDiffusionRequest($drequest)
->setLimit(self::RESULT_LIMIT)
->needDirectChanges(true)
->needChildChanges(true)
->loadHistory();
$raw_commit_identifiers = mpull($history, 'getCommitIdentifier');
$result = array();
foreach ($raw_commit_identifiers as $id) {
$result[] = 'r'.$request->getValue('callsign').$id;
}
return $result;
}
}
diff --git a/src/applications/diffusion/controller/base/DiffusionController.php b/src/applications/diffusion/controller/base/DiffusionController.php
index eee14ec0c6..b128f52dd8 100644
--- a/src/applications/diffusion/controller/base/DiffusionController.php
+++ b/src/applications/diffusion/controller/base/DiffusionController.php
@@ -1,298 +1,309 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
abstract class DiffusionController extends PhabricatorController {
protected $diffusionRequest;
public function willProcessRequest(array $data) {
- $this->diffusionRequest = DiffusionRequest::newFromAphrontRequestDictionary(
- $data);
+ if (isset($data['callsign'])) {
+ $drequest = DiffusionRequest::newFromAphrontRequestDictionary($data);
+ $this->diffusionRequest = $drequest;
+ }
}
public function setDiffusionRequest(DiffusionRequest $request) {
$this->diffusionRequest = $request;
return $this;
}
protected function getDiffusionRequest() {
+ if (!$this->diffusionRequest) {
+ throw new Exception("No Diffusion request object!");
+ }
return $this->diffusionRequest;
}
public function buildStandardPageResponse($view, array $data) {
$page = $this->buildStandardPageView();
$page->setApplicationName('Diffusion');
$page->setBaseURI('/diffusion/');
$page->setTitle(idx($data, 'title'));
$page->setGlyph("\xE2\x89\x88");
$page->setTabs(
array(
'help' => array(
'href' => PhabricatorEnv::getDoclink(
'article/Diffusion_User_Guide.html'),
'name' => 'Help',
),
),
null);
$page->setSearchDefaultScope(PhabricatorSearchScope::SCOPE_COMMITS);
$page->appendChild($view);
$response = new AphrontWebpageResponse();
return $response->setContent($page->render());
}
final protected function buildSideNav($selected, $has_change_view) {
$nav = new AphrontSideNavView();
$navs = array(
'history' => 'History View',
'browse' => 'Browse View',
'change' => 'Change View',
);
if (!$has_change_view) {
unset($navs['change']);
}
$drequest = $this->getDiffusionRequest();
- $repository = $drequest->getRepository();
- $callsign = $repository->getCallsign();
-
- $branch_uri = $drequest->getBranchURIComponent($drequest->getBranch());
- $path_uri = $branch_uri.$drequest->getPath();
- $commit_uri = null;
- $raw_commit = $drequest->getRawCommit();
- if ($raw_commit) {
- $commit_uri = ';'.$drequest->getCommitURIComponent($raw_commit);
- }
+ foreach ($navs as $action => $name) {
+ $href = $drequest->generateURI(
+ array(
+ 'action' => $action,
+ ));
- foreach ($navs as $uri => $name) {
$nav->addNavItem(
phutil_render_tag(
'a',
array(
- 'href' => "/diffusion/{$callsign}/{$uri}/{$path_uri}{$commit_uri}",
+ 'href' => $href,
'class' =>
- ($uri == $selected
+ ($action == $selected
? 'aphront-side-nav-selected'
: null),
),
$name));
}
+
+ // TODO: URI encoding might need to be sorted out for this link.
+
$nav->addNavItem(
phutil_render_tag(
'a',
array(
'href' => '/owners/view/search/'.
- '?repository='.phutil_escape_uri($callsign).
+ '?repository='.phutil_escape_uri($drequest->getCallsign()).
'&path='.phutil_escape_uri('/'.$drequest->getPath()),
),
'Search Owners'));
return $nav;
}
public function buildCrumbs(array $spec = array()) {
$crumbs = new AphrontCrumbsView();
$crumb_list = $this->buildCrumbList($spec);
$crumbs->setCrumbs($crumb_list);
return $crumbs;
}
protected function buildOpenRevisions() {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$path = $drequest->getPath();
$path_map = id(new DiffusionPathIDQuery(array($path)))->loadPathIDs();
$path_id = idx($path_map, $path);
if (!$path_id) {
return null;
}
$revisions = id(new DifferentialRevisionQuery())
->withPath($repository->getID(), $path_id)
->withStatus(DifferentialRevisionQuery::STATUS_OPEN)
->setOrder(DifferentialRevisionQuery::ORDER_PATH_MODIFIED)
->setLimit(10)
->needRelationships(true)
->execute();
if (!$revisions) {
return null;
}
$view = id(new DifferentialRevisionListView())
->setRevisions($revisions)
->setFields(DifferentialRevisionListView::getDefaultFields())
->setUser($this->getRequest()->getUser());
$phids = $view->getRequiredHandlePHIDs();
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
$view->setHandles($handles);
$panel = new AphrontPanelView();
$panel->setHeader('Pending Differential Revisions');
$panel->appendChild($view);
return $panel;
}
private function buildCrumbList(array $spec = array()) {
- $drequest = $this->getDiffusionRequest();
$crumb_list = array();
- $repository = $drequest->getRepository();
+ // On the home page, we don't have a DiffusionRequest.
+ if ($this->diffusionRequest) {
+ $drequest = $this->getDiffusionRequest();
+ $repository = $drequest->getRepository();
+ } else {
+ $drequest = null;
+ $repository = null;
+ }
+
if ($repository) {
$crumb_list[] = phutil_render_tag(
'a',
array(
'href' => '/diffusion/',
),
'Diffusion');
} else {
$crumb_list[] = 'Diffusion';
return $crumb_list;
}
$callsign = $repository->getCallsign();
$repository_name = phutil_escape_html($repository->getName()).' Repository';
if (empty($spec['commit'])) {
$branch_name = $drequest->getBranch();
if ($branch_name) {
$repository_name .= ' ('.phutil_escape_html($branch_name).')';
}
}
if (empty($spec['view']) && empty($spec['commit'])) {
$crumb_list[] = $repository_name;
return $crumb_list;
}
$crumb_list[] = phutil_render_tag(
'a',
array(
'href' => "/diffusion/{$callsign}/",
),
$repository_name);
$raw_commit = $drequest->getRawCommit();
if (isset($spec['commit'])) {
$crumb_list[] = "r{$callsign}{$raw_commit}";
return $crumb_list;
}
$view = $spec['view'];
$path = null;
if (isset($spec['path'])) {
$path = $drequest->getPath();
}
if ($raw_commit) {
$commit_link = DiffusionView::linkCommit(
$repository,
$raw_commit);
} else {
$commit_link = '';
}
switch ($view) {
case 'history':
$view_name = 'History';
break;
case 'browse':
$view_name = 'Browse';
break;
case 'change':
$view_name = 'Change';
$crumb_list[] = phutil_escape_html($path).' ('.$commit_link.')';
return $crumb_list;
}
- $branch_uri = $drequest->getBranchURIComponent($drequest->getBranch());
- $view_root_uri = "/diffusion/{$callsign}/{$view}/{$branch_uri}";
- $jump_href = $view_root_uri;
-
- $view_tail_uri = null;
- if ($raw_commit) {
- $view_tail_uri = ';'.$drequest->getCommitURIComponent($raw_commit);
- }
+ $uri_params = array(
+ 'action' => $view,
+ );
if (!strlen($path)) {
$crumb_list[] = $view_name;
} else {
$crumb_list[] = phutil_render_tag(
'a',
array(
- 'href' => $view_root_uri.$view_tail_uri,
+ 'href' => $drequest->generateURI(
+ array(
+ 'path' => null,
+ ) + $uri_params),
),
$view_name);
$path_parts = explode('/', $path);
do {
$last = array_pop($path_parts);
} while ($last == '');
$path_sections = array();
$thus_far = '';
foreach ($path_parts as $path_part) {
$thus_far .= $path_part.'/';
$path_sections[] = phutil_render_tag(
'a',
array(
- 'href' => $view_root_uri.$thus_far.$view_tail_uri,
+ 'href' => $drequest->generateURI(
+ array(
+ 'path' => $thus_far,
+ ) + $uri_params),
),
phutil_escape_html($path_part));
}
$path_sections[] = phutil_escape_html($last);
$path_sections = '/'.implode('/', $path_sections);
- $jump_href = $view_root_uri.$thus_far.$last;
-
$crumb_list[] = $path_sections;
}
$last_crumb = array_pop($crumb_list);
if ($raw_commit) {
$jump_link = phutil_render_tag(
'a',
array(
- 'href' => $jump_href,
+ 'href' => $drequest->generateURI(
+ array(
+ 'commit' => null,
+ ) + $uri_params),
),
'Jump to HEAD');
$last_crumb .= " @ {$commit_link} ({$jump_link})";
} else {
$last_crumb .= " @ HEAD";
}
$crumb_list[] = $last_crumb;
return $crumb_list;
}
}
diff --git a/src/applications/diffusion/controller/commit/DiffusionCommitController.php b/src/applications/diffusion/controller/commit/DiffusionCommitController.php
index de35431294..8e48354004 100644
--- a/src/applications/diffusion/controller/commit/DiffusionCommitController.php
+++ b/src/applications/diffusion/controller/commit/DiffusionCommitController.php
@@ -1,436 +1,443 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DiffusionCommitController extends DiffusionController {
const CHANGES_LIMIT = 100;
+ public function willProcessRequest(array $data) {
+ // This controller doesn't use blob/path stuff, just pass the dictionary
+ // in directly instead of using the AphrontRequest parsing mechanism.
+ $drequest = DiffusionRequest::newFromDictionary($data);
+ $this->diffusionRequest = $drequest;
+ }
+
public function processRequest() {
$drequest = $this->getDiffusionRequest();
$request = $this->getRequest();
$user = $request->getUser();
$callsign = $drequest->getRepository()->getCallsign();
$content = array();
$content[] = $this->buildCrumbs(array(
'commit' => true,
));
$detail_panel = new AphrontPanelView();
$repository = $drequest->getRepository();
$commit = $drequest->loadCommit();
if (!$commit) {
// TODO: Make more user-friendly.
throw new Exception('This commit has not parsed yet.');
}
$commit_data = $drequest->loadCommitData();
$is_foreign = $commit_data->getCommitDetail('foreign-svn-stub');
if ($is_foreign) {
$subpath = $commit_data->getCommitDetail('svn-subpath');
$error_panel = new AphrontErrorView();
$error_panel->setWidth(AphrontErrorView::WIDTH_WIDE);
$error_panel->setTitle('Commit Not Tracked');
$error_panel->setSeverity(AphrontErrorView::SEVERITY_WARNING);
$error_panel->appendChild(
"This Diffusion repository is configured to track only one ".
"subdirectory of the entire Subversion repository, and this commit ".
"didn't affect the tracked subdirectory ('".
phutil_escape_html($subpath)."'), so no information is available.");
$content[] = $error_panel;
} else {
$engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine();
require_celerity_resource('diffusion-commit-view-css');
require_celerity_resource('phabricator-remarkup-css');
$property_table = $this->renderPropertyTable($commit, $commit_data);
$detail_panel->appendChild(
'<div class="diffusion-commit-view">'.
'<div class="diffusion-commit-dateline">'.
'r'.$callsign.$commit->getCommitIdentifier().
' &middot; '.
phabricator_datetime($commit->getEpoch(), $user).
'</div>'.
'<h1>Revision Detail</h1>'.
'<div class="diffusion-commit-details">'.
$property_table.
'<hr />'.
'<div class="diffusion-commit-message phabricator-remarkup">'.
$engine->markupText($commit_data->getCommitMessage()).
'</div>'.
'</div>'.
'</div>');
$content[] = $detail_panel;
}
$content[] = $this->buildAuditTable($commit);
$content[] = $this->buildComments($commit);
$change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
$drequest);
$changes = $change_query->loadChanges();
$original_changes_count = count($changes);
if ($request->getStr('show_all') !== 'true' &&
$original_changes_count > self::CHANGES_LIMIT) {
$changes = array_slice($changes, 0, self::CHANGES_LIMIT);
}
$change_table = new DiffusionCommitChangeTableView();
$change_table->setDiffusionRequest($drequest);
$change_table->setPathChanges($changes);
$count = count($changes);
$bad_commit = null;
if ($count == 0) {
$bad_commit = queryfx_one(
id(new PhabricatorRepository())->establishConnection('r'),
'SELECT * FROM %T WHERE fullCommitName = %s',
PhabricatorRepository::TABLE_BADCOMMIT,
'r'.$callsign.$commit->getCommitIdentifier());
}
if ($bad_commit) {
$error_panel = new AphrontErrorView();
$error_panel->setWidth(AphrontErrorView::WIDTH_WIDE);
$error_panel->setTitle('Bad Commit');
$error_panel->appendChild(
phutil_escape_html($bad_commit['description']));
$content[] = $error_panel;
} else if ($is_foreign) {
// Don't render anything else.
} else if (!count($changes)) {
$no_changes = new AphrontErrorView();
$no_changes->setWidth(AphrontErrorView::WIDTH_WIDE);
$no_changes->setSeverity(AphrontErrorView::SEVERITY_WARNING);
$no_changes->setTitle('Not Yet Parsed');
// TODO: This can also happen with weird SVN changes that don't do
// anything (or only alter properties?), although the real no-changes case
// is extremely rare and might be impossible to produce organically. We
// should probably write some kind of "Nothing Happened!" change into the
// DB once we parse these changes so we can distinguish between
// "not parsed yet" and "no changes".
$no_changes->appendChild(
"This commit hasn't been fully parsed yet (or doesn't affect any ".
"paths).");
$content[] = $no_changes;
} else {
$change_panel = new AphrontPanelView();
$change_panel->setHeader("Changes (".number_format($count).")");
if ($count !== $original_changes_count) {
$show_all_button = phutil_render_tag(
'a',
array(
'class' => 'button green',
'href' => '?show_all=true',
),
phutil_escape_html('Show All Changes'));
$warning_view = id(new AphrontErrorView())
->setSeverity(AphrontErrorView::SEVERITY_WARNING)
->setTitle(sprintf(
"Showing only the first %d changes out of %s!",
self::CHANGES_LIMIT,
number_format($original_changes_count)));
$change_panel->appendChild($warning_view);
$change_panel->addButton($show_all_button);
}
$change_panel->appendChild($change_table);
$content[] = $change_panel;
$changesets = DiffusionPathChange::convertToDifferentialChangesets(
$changes);
$vcs = $repository->getVersionControlSystem();
switch ($vcs) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$vcs_supports_directory_changes = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$vcs_supports_directory_changes = false;
break;
default:
throw new Exception("Unknown VCS.");
}
$references = array();
foreach ($changesets as $key => $changeset) {
$file_type = $changeset->getFileType();
if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
if (!$vcs_supports_directory_changes) {
unset($changesets[$key]);
continue;
}
}
- $branch = $drequest->getBranchURIComponent(
- $drequest->getBranch());
- $filename = $changeset->getFilename();
- $reference = "{$branch}{$filename};".$drequest->getCommit();
- $references[$key] = $reference;
+ $references[$key] = $drequest->generateURI(
+ array(
+ 'action' => 'rendering-ref',
+ 'path' => $changeset->getFilename(),
+ ));
}
// TOOD: Some parts of the views still rely on properties of the
// DifferentialChangeset. Make the objects ephemeral to make sure we don't
// accidentally save them, and then set their ID to the appropriate ID for
// this application (the path IDs).
$pquery = new DiffusionPathIDQuery(mpull($changesets, 'getFilename'));
$path_ids = $pquery->loadPathIDs();
foreach ($changesets as $changeset) {
$changeset->makeEphemeral();
$changeset->setID($path_ids[$changeset->getFilename()]);
}
$change_list = new DifferentialChangesetListView();
$change_list->setChangesets($changesets);
$change_list->setRenderingReferences($references);
$change_list->setRenderURI('/diffusion/'.$callsign.'/diff/');
$change_list->setUser($user);
$change_list->setInlineCommentControllerURI(
'/diffusion/inline/'.phutil_escape_uri($commit->getPHID()).'/');
// TODO: This is pretty awkward, unify the CSS between Diffusion and
// Differential better.
require_celerity_resource('differential-core-view-css');
$change_list =
'<div class="differential-primary-pane">'.
$change_list->render().
'</div>';
$content[] = $change_list;
}
$content[] = $this->buildAddCommentView($commit);
return $this->buildStandardPageResponse(
$content,
array(
'title' => 'r'.$callsign.$commit->getCommitIdentifier(),
));
}
private function renderPropertyTable(
PhabricatorRepositoryCommit $commit,
PhabricatorRepositoryCommitData $data) {
$phids = array();
if ($data->getCommitDetail('authorPHID')) {
$phids[] = $data->getCommitDetail('authorPHID');
}
if ($data->getCommitDetail('reviewerPHID')) {
$phids[] = $data->getCommitDetail('reviewerPHID');
}
if ($data->getCommitDetail('differential.revisionPHID')) {
$phids[] = $data->getCommitDetail('differential.revisionPHID');
}
$handles = array();
if ($phids) {
$handles = id(new PhabricatorObjectHandleData($phids))
->loadHandles();
}
$props = array();
$author_phid = $data->getCommitDetail('authorPHID');
if ($data->getCommitDetail('authorPHID')) {
$props['Author'] = $handles[$author_phid]->renderLink();
} else {
$props['Author'] = phutil_escape_html($data->getAuthorName());
}
$reviewer_phid = $data->getCommitDetail('reviewerPHID');
$reviewer_name = $data->getCommitDetail('reviewerName');
if ($reviewer_phid) {
$props['Reviewer'] = $handles[$reviewer_phid]->renderLink();
} else if ($reviewer_name) {
$props['Reviewer'] = phutil_escape_html($reviewer_name);
}
$revision_phid = $data->getCommitDetail('differential.revisionPHID');
if ($revision_phid) {
$props['Differential Revision'] = $handles[$revision_phid]->renderLink();
}
if ($commit->getAuditStatus()) {
$props['Audit'] = PhabricatorAuditCommitStatusConstants::getStatusName(
$commit->getAuditStatus());
}
$request = $this->getDiffusionRequest();
$contains = DiffusionContainsQuery::newFromDiffusionRequest($request);
$branches = $contains->loadContainingBranches();
if ($branches) {
// TODO: Separate these into 'tracked' and other; link tracked branches.
$branches = implode(', ', array_keys($branches));
$branches = phutil_escape_html($branches);
$props['Branches'] = $branches;
}
$rows = array();
foreach ($props as $key => $value) {
$rows[] =
'<tr>'.
'<th>'.$key.':</th>'.
'<td>'.$value.'</td>'.
'</tr>';
}
return
'<table class="diffusion-commit-properties">'.
implode("\n", $rows).
'</table>';
}
private function buildAuditTable($commit) {
$user = $this->getRequest()->getUser();
$query = new PhabricatorAuditQuery();
$query->withCommitPHIDs(array($commit->getPHID()));
$audits = $query->execute();
$view = new PhabricatorAuditListView();
$view->setAudits($audits);
$phids = $view->getRequiredHandlePHIDs();
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
$view->setHandles($handles);
$view->setAuthorityPHIDs(
PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user));
$panel = new AphrontPanelView();
$panel->setHeader('Audits');
$panel->appendChild($view);
return $panel;
}
private function buildComments($commit) {
$user = $this->getRequest()->getUser();
$comments = id(new PhabricatorAuditComment())->loadAllWhere(
'targetPHID = %s ORDER BY dateCreated ASC',
$commit->getPHID());
$view = new DiffusionCommentListView();
$view->setUser($user);
$view->setComments($comments);
$phids = $view->getRequiredHandlePHIDs();
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
$view->setHandles($handles);
return $view;
}
private function buildAddCommentView($commit) {
$user = $this->getRequest()->getUser();
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
Javelin::initBehavior(
'differential-keyboard-navigation',
array(
// TODO: Make this comment panel hauntable
'haunt' => null,
));
$draft = id(new PhabricatorDraft())->loadOneWhere(
'authorPHID = %s AND draftKey = %s',
$user->getPHID(),
'diffusion-audit-'.$commit->getID());
if ($draft) {
$draft = $draft->getDraft();
} else {
$draft = null;
}
$form = id(new AphrontFormView())
->setUser($user)
->setAction('/audit/addcomment/')
->addHiddenInput('commit', $commit->getPHID())
->appendChild(
id(new AphrontFormSelectControl())
->setLabel('Action')
->setName('action')
->setID('audit-action')
->setOptions(PhabricatorAuditActionConstants::getActionNameMap()))
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Comments')
->setName('content')
->setValue($draft)
->setID('audit-content')
->setCaption(phutil_render_tag(
'a',
array(
'href' => PhabricatorEnv::getDoclink(
'article/Remarkup_Reference.html'),
'tabindex' => '-1',
'target' => '_blank',
),
'Formatting Reference')))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue($is_serious ? 'Submit' : 'Cook the Books'));
$panel = new AphrontPanelView();
$panel->setHeader($is_serious ? 'Audit Commit' : 'Creative Accounting');
$panel->appendChild($form);
require_celerity_resource('phabricator-transaction-view-css');
Javelin::initBehavior('audit-preview', array(
'uri' => '/audit/preview/'.$commit->getID().'/',
'preview' => 'audit-preview',
'content' => 'audit-content',
'action' => 'audit-action',
));
$preview_panel =
'<div class="aphront-panel-preview">
<div id="audit-preview">
<div class="aphront-panel-preview-loading-text">
Loading preview...
</div>
</div>
</div>';
$view = new AphrontNullView();
$view->appendChild($panel);
$view->appendChild($preview_panel);
return $view;
}
}
diff --git a/src/applications/diffusion/controller/commit/__init__.php b/src/applications/diffusion/controller/commit/__init__.php
index 1b04ed438a..ebcda3060d 100644
--- a/src/applications/diffusion/controller/commit/__init__.php
+++ b/src/applications/diffusion/controller/commit/__init__.php
@@ -1,46 +1,47 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/audit/constants/action');
phutil_require_module('phabricator', 'applications/audit/constants/commitstatus');
phutil_require_module('phabricator', 'applications/audit/editor/comment');
phutil_require_module('phabricator', 'applications/audit/query/audit');
phutil_require_module('phabricator', 'applications/audit/storage/auditcomment');
phutil_require_module('phabricator', 'applications/audit/view/list');
phutil_require_module('phabricator', 'applications/differential/constants/changetype');
phutil_require_module('phabricator', 'applications/differential/view/changesetlistview');
phutil_require_module('phabricator', 'applications/diffusion/controller/base');
phutil_require_module('phabricator', 'applications/diffusion/data/pathchange');
phutil_require_module('phabricator', 'applications/diffusion/query/contains/base');
phutil_require_module('phabricator', 'applications/diffusion/query/pathchange/base');
phutil_require_module('phabricator', 'applications/diffusion/query/pathid/base');
+phutil_require_module('phabricator', 'applications/diffusion/request/base');
phutil_require_module('phabricator', 'applications/diffusion/view/commentlist');
phutil_require_module('phabricator', 'applications/diffusion/view/commitchangetable');
phutil_require_module('phabricator', 'applications/draft/storage/draft');
phutil_require_module('phabricator', 'applications/markup/engine');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'applications/repository/constants/repositorytype');
phutil_require_module('phabricator', 'applications/repository/storage/repository');
phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'infrastructure/env');
phutil_require_module('phabricator', 'infrastructure/javelin/api');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/select');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phabricator', 'view/null');
phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('DiffusionCommitController.php');
diff --git a/src/applications/diffusion/controller/diff/DiffusionDiffController.php b/src/applications/diffusion/controller/diff/DiffusionDiffController.php
index 606cf79c82..5da607e117 100644
--- a/src/applications/diffusion/controller/diff/DiffusionDiffController.php
+++ b/src/applications/diffusion/controller/diff/DiffusionDiffController.php
@@ -1,86 +1,83 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DiffusionDiffController extends DiffusionController {
public function willProcessRequest(array $data) {
- $request = $this->getRequest();
- if ($request->getStr('ref')) {
- $parts = explode(';', $request->getStr('ref'));
- $data['path'] = idx($parts, 0);
- $data['commit'] = idx($parts, 1);
- }
+ $data = $data + array(
+ 'dblob' => $this->getRequest()->getStr('ref'),
+ );
+ $drequest = DiffusionRequest::newFromAphrontRequestDictionary($data);
- $this->diffusionRequest = DiffusionRequest::newFromAphrontRequestDictionary(
- $data);
+ $this->diffusionRequest = $drequest;
}
public function processRequest() {
$drequest = $this->getDiffusionRequest();
$request = $this->getRequest();
$user = $request->getUser();
$diff_query = DiffusionDiffQuery::newFromDiffusionRequest($drequest);
$changeset = $diff_query->loadChangeset();
if (!$changeset) {
return new Aphront404Response();
}
$parser = new DifferentialChangesetParser();
$parser->setChangeset($changeset);
$parser->setRenderingReference($diff_query->getRenderingReference());
$parser->setMarkupEngine(
PhabricatorMarkupEngine::newDiffusionMarkupEngine());
$pquery = new DiffusionPathIDQuery(array($changeset->getFilename()));
$ids = $pquery->loadPathIDs();
$path_id = $ids[$changeset->getFilename()];
$parser->setLeftSideCommentMapping($path_id, false);
$parser->setRightSideCommentMapping($path_id, true);
$parser->setWhitespaceMode(
DifferentialChangesetParser::WHITESPACE_SHOW_ALL);
$inlines = id(new PhabricatorAuditInlineComment())->loadAllWhere(
'commitPHID = %s AND pathID = %d AND
(authorPHID = %s OR auditCommentID IS NOT NULL)',
$drequest->loadCommit()->getPHID(),
$path_id,
$user->getPHID());
if ($inlines) {
foreach ($inlines as $inline) {
$parser->parseInlineComment($inline);
}
$phids = mpull($inlines, 'getAuthorPHID');
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
$parser->setHandles($handles);
}
$spec = $request->getStr('range');
list($range_s, $range_e, $mask) =
DifferentialChangesetParser::parseRangeSpecification($spec);
$output = $parser->render($range_s, $range_e, $mask);
return id(new PhabricatorChangesetResponse())
->setRenderedChangeset($output);
}
}
diff --git a/src/applications/diffusion/controller/file/DiffusionBrowseFileController.php b/src/applications/diffusion/controller/file/DiffusionBrowseFileController.php
index b8d1dfc4c9..bf559965c4 100644
--- a/src/applications/diffusion/controller/file/DiffusionBrowseFileController.php
+++ b/src/applications/diffusion/controller/file/DiffusionBrowseFileController.php
@@ -1,485 +1,490 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DiffusionBrowseFileController extends DiffusionController {
// Image types we want to display inline using <img> tags
protected $imageTypes = array(
'png' => 'image/png',
'gif' => 'image/gif',
'ico' => 'image/png',
'jpg' => 'image/jpeg',
'jpeg'=> 'image/jpeg'
);
// Document types that should trigger link to ?view=raw
protected $documentTypes = array(
'pdf'=> 'application/pdf',
'ps' => 'application/postscript',
);
public function processRequest() {
// Build the view selection form.
$select_map = array(
'highlighted' => 'View as Highlighted Text',
'blame' => 'View as Highlighted Text with Blame',
'plain' => 'View as Plain Text',
'plainblame' => 'View as Plain Text with Blame',
'raw' => 'View as raw document',
);
$request = $this->getRequest();
$drequest = $this->getDiffusionRequest();
$path = $drequest->getPath();
$selected = $request->getStr('view');
$needs_blame = ($selected == 'blame' || $selected == 'plainblame');
$file_query = DiffusionFileContentQuery::newFromDiffusionRequest(
$this->diffusionRequest);
$file_query->setNeedsBlame($needs_blame);
$file_query->loadFileContent();
$data = $file_query->getRawData();
if ($selected === 'raw') {
$response = new AphrontFileResponse();
$response->setContent($data);
$mime_type = $this->getDocumentType($path);
if ($mime_type) {
$response->setMimeType($mime_type);
} else {
$as_filename = idx(pathinfo($path), 'basename');
$response->setDownload($as_filename);
}
return $response;
}
$select = '<select name="view">';
foreach ($select_map as $k => $v) {
$option = phutil_render_tag(
'option',
array(
'value' => $k,
'selected' => ($k == $selected) ? 'selected' : null,
),
phutil_escape_html($v));
$select .= $option;
}
$select .= '</select>';
require_celerity_resource('diffusion-source-css');
$edit_button = '';
$user = $request->getUser();
if ($user) {
$line = 1;
$repository = $this->getDiffusionRequest()->getRepository();
$editor_link = $user->loadEditorLink($path, $line, $repository);
if ($editor_link) {
$edit_button = phutil_render_tag(
'a',
array(
'href' => $editor_link,
'class' => 'button',
),
'Edit');
}
}
$view_select_panel = new AphrontPanelView();
$view_select_form = phutil_render_tag(
'form',
array(
'action' => $request->getRequestURI(),
'method' => 'get',
'class' => 'diffusion-browse-type-form',
),
$select.
' <button>View</button> '.
$edit_button);
$view_select_panel->appendChild($view_select_form);
$view_select_panel->appendChild('<div style="clear: both;"></div>');
// Build the content of the file.
$corpus = $this->buildCorpus(
$selected,
$file_query,
$needs_blame,
$drequest,
$path,
$data
);
// Render the page.
$content = array();
$content[] = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'browse',
));
$content[] = $view_select_panel;
$content[] = $corpus;
$content[] = $this->buildOpenRevisions();
$nav = $this->buildSideNav('browse', true);
$nav->appendChild($content);
$basename = basename($this->getDiffusionRequest()->getPath());
return $this->buildStandardPageResponse(
$nav,
array(
'title' => $basename,
));
}
/**
* Returns a content-type corrsponding to an image file extension
*
* @param string $path File path
* @return mixed A content-type string or NULL if path doesn't end with a
* recognized image extension
*/
public function getImageType($path) {
$ext = pathinfo($path);
$ext = idx($ext, 'extension');
return idx($this->imageTypes, $ext);
}
/**
* Returns a content-type corresponding to an document file extension
*
* @param string $path File path
* @return mixed A content-type string or NULL if path doesn't end with a
* recognized document extension
*/
public function getDocumentType($path) {
$ext = pathinfo($path);
$ext = idx($ext, 'extension');
return idx($this->documentTypes, $ext);
}
private function buildCorpus($selected,
$file_query,
$needs_blame,
$drequest,
$path,
$data) {
$image_type = $this->getImageType($path);
if ($image_type && !$selected) {
$corpus = phutil_render_tag(
'img',
array(
'style' => 'padding-bottom: 10px',
'src' => 'data:'.$image_type.';base64,'.base64_encode($data),
)
);
return $corpus;
}
$document_type = $this->getDocumentType($path);
if (($document_type && !$selected) || !phutil_is_utf8($data)) {
$data = $file_query->getRawData();
$document_type_description = $document_type ? $document_type : 'binary';
$corpus = phutil_render_tag(
'p',
array(
'style' => 'text-align: center;'
),
phutil_render_tag(
'a',
array(
'href' => '?view=raw',
'class' => 'button'
),
"View $document_type_description"
)
);
return $corpus;
}
// TODO: blame of blame.
switch ($selected) {
case 'plain':
$style =
"margin: 1em 2em; width: 90%; height: 80em; font-family: monospace";
$corpus = phutil_render_tag(
'textarea',
array(
'style' => $style,
),
phutil_escape_html($file_query->getRawData()));
break;
case 'plainblame':
$style =
"margin: 1em 2em; width: 90%; height: 80em; font-family: monospace";
list($text_list, $rev_list, $blame_dict) =
$file_query->getBlameData();
$rows = array();
foreach ($text_list as $k => $line) {
$rev = $rev_list[$k];
if (isset($blame_dict[$rev]['handle'])) {
$author = $blame_dict[$rev]['handle']->getName();
} else {
$author = $blame_dict[$rev]['author'];
}
$rows[] =
sprintf("%-10s %-20s %s", substr($rev, 0, 7), $author, $line);
}
$corpus = phutil_render_tag(
'textarea',
array(
'style' => $style,
),
phutil_escape_html(implode("\n", $rows)));
break;
case 'highlighted':
case 'blame':
default:
require_celerity_resource('syntax-highlighting-css');
list($text_list, $rev_list, $blame_dict) = $file_query->getBlameData();
$text_list = implode("\n", $text_list);
$text_list = PhabricatorSyntaxHighlighter::highlightWithFilename(
$path,
$text_list);
$text_list = explode("\n", $text_list);
$rows = $this->buildDisplayRows($text_list, $rev_list, $blame_dict,
$needs_blame, $drequest, $file_query, $selected);
$corpus_table = phutil_render_tag(
'table',
array(
'class' => "diffusion-source remarkup-code PhabricatorMonospaced",
),
implode("\n", $rows));
$corpus = phutil_render_tag(
'div',
array(
'style' => 'padding: 0pt 2em;',
),
$corpus_table);
break;
}
return $corpus;
}
private function buildDisplayRows($text_list, $rev_list, $blame_dict,
$needs_blame, DiffusionRequest $drequest, $file_query, $selected) {
$last_rev = null;
$color = '#eeeeee';
$rows = array();
$n = 1;
$view = $this->getRequest()->getStr('view');
if ($blame_dict) {
$epoch_list = ipull($blame_dict, 'epoch');
$epoch_max = max($epoch_list);
$epoch_min = min($epoch_list);
$epoch_range = $epoch_max - $epoch_min + 1;
}
$targ = '';
$min_line = 0;
$line = $drequest->getLine();
if (strpos($line, '-') !== false) {
list($min, $max) = explode('-', $line, 2);
$min_line = min($min, $max);
$max_line = max($min, $max);
} else if (strlen($line)) {
$min_line = $line;
$max_line = $line;
}
foreach ($text_list as $k => $line) {
if ($needs_blame) {
// If the line's rev is same as the line above, show empty content
// with same color; otherwise generate blame info. The newer a change
// is, the darker the color.
$rev = $rev_list[$k];
if ($last_rev == $rev) {
$blame_info =
($file_query->getSupportsBlameOnBlame() ?
'<th style="background: '.$color.'; width: 2em;"></th>' : '').
'<th style="background: '.$color.'; width: 9em;"></th>'.
'<th style="background: '.$color.'"></th>';
} else {
$revision_time = null;
if ($blame_dict) {
$color_number = (int)(0xEE -
0xEE * ($blame_dict[$rev]['epoch'] - $epoch_min) / $epoch_range);
$color = sprintf('#%02xee%02x', $color_number, $color_number);
$revision_time = phabricator_datetime(
$blame_dict[$rev]['epoch'],
$this->getRequest()->getUser());
}
$revision_link = self::renderRevision(
$drequest,
substr($rev, 0, 7));
if (!$file_query->getSupportsBlameOnBlame()) {
$prev_link = '';
} else {
$prev_rev = $file_query->getPrevRev($rev);
$path = $drequest->getPath();
$prev_link = self::renderBrowse(
$drequest,
$path,
"\xC2\xAB",
$prev_rev,
$n,
$selected,
'Blame previous revision');
$prev_link = phutil_render_tag(
'th',
array(
'class' => 'diffusion-wide-link',
'style' => 'background: '.$color.'; width: 2em;',
),
$prev_link);
}
if (isset($blame_dict[$rev]['handle'])) {
$author_link = $blame_dict[$rev]['handle']->renderLink();
} else {
$author_link = phutil_escape_html($blame_dict[$rev]['author']);
}
$blame_info =
$prev_link .
'<th style="background: '.$color.'; width: 12em;" title="'.
phutil_escape_html($revision_time).'">'.$revision_link.'</th>'.
'<th style="background: '.$color.'; width: 12em'.
'; font-weight: normal; color: #333;">'.$author_link.'</th>';
$last_rev = $rev;
}
} else {
$blame_info = null;
}
// Highlight the line of interest if needed.
if ($min_line > 0 && ($n >= $min_line && $n <= $max_line)) {
$tr = '<tr style="background: #ffff00;">';
if ($targ == '') {
$targ = '<a id="scroll_target"></a>';
Javelin::initBehavior('diffusion-jump-to',
array('target' => 'scroll_target'));
}
} else {
$tr = '<tr>';
$targ = null;
}
- // Create the row display.
- $uri_path = $drequest->getUriPath();
- $uri_rev = $drequest->getStableCommitName();
- $uri_view = $view
- ? '?view='.$view
- : null;
-
- $l = phutil_render_tag(
+ $href = $drequest->generateURI(
+ array(
+ 'action' => 'browse',
+ 'stable' => true,
+ ));
+ $href = (string)$href;
+
+ $query_params = null;
+ if ($view) {
+ $query_params = '?view='.$view;
+ }
+
+ $link = phutil_render_tag(
'a',
array(
- 'href' => $uri_path.';'.$uri_rev.'$'.$n.$uri_view,
+ 'href' => $href.'$'.$n.$query_params,
),
$n);
$rows[] = $tr.$blame_info.
- '<th class="diffusion-wide-link">'.$l.'</th>'.
+ '<th class="diffusion-wide-link">'.$link.'</th>'.
'<td>'.$targ.$line.'</td></tr>';
++$n;
}
return $rows;
}
private static function renderRevision(DiffusionRequest $drequest,
$revision) {
$callsign = $drequest->getCallsign();
$name = 'r'.$callsign.$revision;
return phutil_render_tag(
'a',
array(
'href' => '/'.$name,
),
$name
);
}
private static function renderBrowse(
DiffusionRequest $drequest,
$path,
$name = null,
$rev = null,
$line = null,
$view = null,
$title = null) {
$callsign = $drequest->getCallsign();
if ($name === null) {
$name = $path;
}
$at = null;
if ($rev) {
$at = ';'.$rev;
}
if ($view) {
$view = '?view='.$view;
}
if ($line) {
$line = '$'.$line;
}
return phutil_render_tag(
'a',
array(
'href' => "/diffusion/{$callsign}/browse/{$path}{$at}{$line}{$view}",
'title' => $title,
),
$name
);
}
}
diff --git a/src/applications/diffusion/controller/pathcomplete/DiffusionPathCompleteController.php b/src/applications/diffusion/controller/pathcomplete/DiffusionPathCompleteController.php
index 2efcbdd60f..69ed227b71 100644
--- a/src/applications/diffusion/controller/pathcomplete/DiffusionPathCompleteController.php
+++ b/src/applications/diffusion/controller/pathcomplete/DiffusionPathCompleteController.php
@@ -1,67 +1,67 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DiffusionPathCompleteController extends DiffusionController {
public function willProcessRequest(array $data) {
// Don't build a DiffusionRequest.
}
public function processRequest() {
$request = $this->getRequest();
$repository_phid = $request->getStr('repositoryPHID');
$repository = id(new PhabricatorRepository())->loadOneWhere(
'phid = %s',
$repository_phid);
if (!$repository) {
return new Aphront400Response();
}
$query_path = $request->getStr('q');
$query_path = ltrim($query_path, '/');
if (preg_match('@/$@', $query_path)) {
$query_dir = $query_path;
} else {
$query_dir = dirname($query_path);
if ($query_dir == '.') {
$query_dir = '';
}
}
- $drequest = DiffusionRequest::newFromAphrontRequestDictionary(
+ $drequest = DiffusionRequest::newFromDictionary(
array(
- 'callsign' => $repository->getCallsign(),
- 'path' => ':/'.$query_dir,
+ 'repository' => $repository,
+ 'path' => $query_dir,
));
$browse_query = DiffusionBrowseQuery::newFromDiffusionRequest($drequest);
$paths = $browse_query->loadPaths();
$output = array();
foreach ($paths as $path) {
$full_path = $query_dir.$path->getPath();
if ($path->getFileType() == DifferentialChangeType::FILE_DIRECTORY) {
$full_path .= '/';
}
$output[] = array('/'.$full_path, null, substr(md5($full_path), 0, 7));
}
return id(new AphrontAjaxResponse())->setContent($output);
}
}
diff --git a/src/applications/diffusion/controller/pathvalidate/DiffusionPathValidateController.php b/src/applications/diffusion/controller/pathvalidate/DiffusionPathValidateController.php
index d539c4db39..6a74f03055 100644
--- a/src/applications/diffusion/controller/pathvalidate/DiffusionPathValidateController.php
+++ b/src/applications/diffusion/controller/pathvalidate/DiffusionPathValidateController.php
@@ -1,79 +1,79 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DiffusionPathValidateController extends DiffusionController {
public function willProcessRequest(array $data) {
// Don't build a DiffusionRequest.
}
public function processRequest() {
$request = $this->getRequest();
$repository_phid = $request->getStr('repositoryPHID');
$repository = id(new PhabricatorRepository())->loadOneWhere(
'phid = %s',
$repository_phid);
if (!$repository) {
return new Aphront400Response();
}
$path = $request->getStr('path');
$path = ltrim($path, '/');
- $drequest = DiffusionRequest::newFromAphrontRequestDictionary(
+ $drequest = DiffusionRequest::newFromDictionary(
array(
- 'callsign' => $repository->getCallsign(),
- 'path' => ':/'.$path,
+ 'repository' => $repository,
+ 'path' => $path,
));
$browse_query = DiffusionBrowseQuery::newFromDiffusionRequest($drequest);
$browse_query->needValidityOnly(true);
$valid = $browse_query->loadPaths();
if (!$valid) {
switch ($browse_query->getReasonForEmptyResultSet()) {
case DiffusionBrowseQuery::REASON_IS_FILE:
$valid = true;
break;
case DiffusionBrowseQuery::REASON_IS_EMPTY:
$valid = true;
break;
}
}
$output = array(
'valid' => (bool)$valid,
);
if (!$valid) {
$branch = $drequest->getBranch();
if ($branch) {
$message = 'Not found in '.$branch;
} else {
$message = 'Not found at HEAD';
}
} else {
$message = 'OK';
}
$output['message'] = $message;
return id(new AphrontAjaxResponse())->setContent($output);
}
}
diff --git a/src/applications/diffusion/query/diff/git/DiffusionGitDiffQuery.php b/src/applications/diffusion/query/diff/git/DiffusionGitDiffQuery.php
index e2ce756485..b7a34f4d83 100644
--- a/src/applications/diffusion/query/diff/git/DiffusionGitDiffQuery.php
+++ b/src/applications/diffusion/query/diff/git/DiffusionGitDiffQuery.php
@@ -1,97 +1,97 @@
<?php
/*
- * Copyright 2011 Facebook, Inc.
+ * Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DiffusionGitDiffQuery extends DiffusionDiffQuery {
protected function executeQuery() {
$drequest = $this->getRequest();
$repository = $drequest->getRepository();
- if (!$drequest->getRawCommit()) {
- $effective_commit = $this->getEffectiveCommit();
- if (!$effective_commit) {
- return null;
- }
- // TODO: This side effect is kind of skethcy.
- $drequest->setCommit($effective_commit);
- } else {
- $effective_commit = $drequest->getCommit();
+ $effective_commit = $this->getEffectiveCommit();
+ if (!$effective_commit) {
+ return null;
}
+ // TODO: This side effect is kind of skethcy.
+ $drequest->setCommit($effective_commit);
$options = array(
'-M',
'-C',
'--no-ext-diff',
'--no-color',
'--src-prefix=a/',
'--dst-prefix=b/',
'-U65535',
);
$options = implode(' ', $options);
try {
list($raw_diff) = $repository->execxLocalCommand(
'diff %C %s^ %s -- %s',
$options,
$effective_commit,
$effective_commit,
$drequest->getPath());
} catch (CommandException $ex) {
// Check if this is the root commit by seeing if it has parents.
list($parents) = $repository->execxLocalCommand(
'log --format=%s %s --',
'%P', // "parents"
$effective_commit);
if (!strlen(trim($parents))) {
// No parents means we're looking at the root revision. Diff against
// the empty tree hash instead, since there is no parent so "^" does
// not work. See ArcanistGitAPI for more discussion.
list($raw_diff) = $repository->execxLocalCommand(
'diff %C %s %s -- %s',
$options,
ArcanistGitAPI::GIT_MAGIC_ROOT_COMMIT,
$effective_commit,
$drequest->getPath());
} else {
throw $ex;
}
}
+ if (!$raw_diff) {
+ return null;
+ }
+
$parser = new ArcanistDiffParser();
$try_encoding = $repository->getDetail('encoding');
if ($try_encoding) {
$parser->setTryEncoding($try_encoding);
}
$parser->setDetectBinaryFiles(true);
$changes = $parser->parseDiff($raw_diff);
$diff = DifferentialDiff::newFromRawChanges($changes);
$changesets = $diff->getChangesets();
$changeset = reset($changesets);
- $this->renderingReference =
- $drequest->getBranchURIComponent($drequest->getBranch()).
- $drequest->getPath().';'.
- $drequest->getCommit();
+ $this->renderingReference = $drequest->generateURI(
+ array(
+ 'action' => 'rendering-ref',
+ ));
return $changeset;
}
}
diff --git a/src/applications/diffusion/query/diff/mercurial/DiffusionMercurialDiffQuery.php b/src/applications/diffusion/query/diff/mercurial/DiffusionMercurialDiffQuery.php
index 1df0c97a00..7cfe68e988 100644
--- a/src/applications/diffusion/query/diff/mercurial/DiffusionMercurialDiffQuery.php
+++ b/src/applications/diffusion/query/diff/mercurial/DiffusionMercurialDiffQuery.php
@@ -1,62 +1,62 @@
<?php
/*
- * Copyright 2011 Facebook, Inc.
+ * Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DiffusionMercurialDiffQuery extends DiffusionDiffQuery {
protected function executeQuery() {
$drequest = $this->getRequest();
$repository = $drequest->getRepository();
$effective_commit = $this->getEffectiveCommit();
if (!$effective_commit) {
return null;
}
// TODO: This side effect is kind of skethcy.
$drequest->setCommit($effective_commit);
$path = $drequest->getPath();
list($raw_diff) = $repository->execxLocalCommand(
'diff -U %d --git --change %s -- %s',
65535,
$effective_commit,
$path);
$parser = new ArcanistDiffParser();
$try_encoding = $repository->getDetail('encoding');
if ($try_encoding) {
$parser->setTryEncoding($try_encoding);
}
$parser->setDetectBinaryFiles(true);
$changes = $parser->parseDiff($raw_diff);
$diff = DifferentialDiff::newFromRawChanges($changes);
$changesets = $diff->getChangesets();
$changeset = reset($changesets);
- $this->renderingReference =
- $drequest->getBranchURIComponent($drequest->getBranch()).
- $drequest->getPath().';'.
- $drequest->getCommit();
+ $this->renderingReference = $drequest->generateURI(
+ array(
+ 'action' => 'rendering-ref',
+ ));
return $changeset;
}
}
diff --git a/src/applications/diffusion/request/base/DiffusionRequest.php b/src/applications/diffusion/request/base/DiffusionRequest.php
index 12d2dd3361..ec0ff3b289 100644
--- a/src/applications/diffusion/request/base/DiffusionRequest.php
+++ b/src/applications/diffusion/request/base/DiffusionRequest.php
@@ -1,177 +1,463 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
- * TODO: This might need to be concrete-extensible, but straighten out the
- * class hierarchy here.
+ * Contains logic to parse Diffusion requests, which have a complicated URI
+ * structure.
+ *
+ *
+ * @task new Creating Requests
+ * @task uri Managing Diffusion URIs
+ *
+ * @group diffusion
*/
-class DiffusionRequest {
+abstract class DiffusionRequest {
protected $callsign;
protected $path;
protected $line;
protected $commit;
protected $branch;
protected $repository;
protected $repositoryCommit;
protected $repositoryCommitData;
protected $stableCommitName;
+ abstract protected function getSupportsBranches();
+ abstract protected function didInitialize();
+
+
+/* -( Creating Requests )-------------------------------------------------- */
+
+
+ /**
+ * Create a new synthetic request from a parameter dictionary. If you need
+ * a @{class:DiffusionRequest} object in order to issue a DiffusionQuery, you
+ * can use this method to build one.
+ *
+ * Parameters are:
+ *
+ * - `callsign` Repository callsign. Provide this or `repository`.
+ * - `repository` Repository object. Provide this or `callsign`.
+ * - `branch` Optional, branch name.
+ * - `path` Optional, file path.
+ * - `commit` Optional, commit identifier.
+ * - `line` Optional, line range.
+ *
+ * @param map See documentation.
+ * @return DiffusionRequest New request object.
+ * @task new
+ */
+ final public static function newFromDictionary(array $data) {
+ if (isset($data['repository']) && isset($data['callsign'])) {
+ throw new Exception(
+ "Specify 'repository' or 'callsign', but not both.");
+ } else if (!isset($data['repository']) && !isset($data['callsign'])) {
+ throw new Exception(
+ "One of 'repository' and 'callsign' is required.");
+ }
+
+ if (isset($data['repository'])) {
+ $object = self::newFromRepository($data['repository']);
+ } else {
+ $object = self::newFromCallsign($data['callsign']);
+ }
+ $object->initializeFromDictionary($data);
+ return $object;
+ }
+
+
+ /**
+ * Create a new request from an Aphront request dictionary. This is an
+ * internal method that you generally should not call directly; instead,
+ * call @{method:newFromDictionary}.
+ *
+ * @param map Map of Aphront request data.
+ * @return DiffusionRequest New request object.
+ * @task new
+ */
+ final public static function newFromAphrontRequestDictionary(array $data) {
+ $callsign = phutil_unescape_uri_path_component(idx($data, 'callsign'));
+ $object = self::newFromCallsign($callsign);
+
+ $use_branches = $object->getSupportsBranches();
+ $parsed = self::parseRequestBlob(idx($data, 'dblob'), $use_branches);
+
+ $object->initializeFromDictionary($parsed);
+ return $object;
+ }
+
+
+ /**
+ * Internal.
+ *
+ * @task new
+ */
final private function __construct() {
// <private>
}
- final public static function newFromAphrontRequestDictionary(array $data) {
- $vcs = null;
- $repository = null;
- $callsign = idx($data, 'callsign');
- if ($callsign) {
- $repository = id(new PhabricatorRepository())->loadOneWhere(
- 'callsign = %s',
- $callsign);
- if (!$repository) {
- throw new Exception("No such repository '{$callsign}'.");
- }
- $vcs = $repository->getVersionControlSystem();
+ /**
+ * Internal. Use @{method:newFromDictionary}, not this method.
+ *
+ * @param string Repository callsign.
+ * @return DiffusionRequest New request object.
+ * @task new
+ */
+ final private static function newFromCallsign($callsign) {
+ $repository = id(new PhabricatorRepository())->loadOneWhere(
+ 'callsign = %s',
+ $callsign);
+
+ if (!$repository) {
+ throw new Exception("No such repository '{$callsign}'.");
}
- switch ($vcs) {
- case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
- $class = 'DiffusionGitRequest';
- break;
- case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
- $class = 'DiffusionSvnRequest';
- break;
- case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
- $class = 'DiffusionMercurialRequest';
- break;
- default:
- $class = 'DiffusionRequest';
- break;
+ return self::newFromRepository($repository);
+ }
+
+
+ /**
+ * Internal. Use @{method:newFromDictionary}, not this method.
+ *
+ * @param PhabricatorRepository Repository object.
+ * @return DiffusionRequest New request object.
+ * @task new
+ */
+ final private static function newFromRepository(
+ PhabricatorRepository $repository) {
+
+ $map = array(
+ PhabricatorRepositoryType::REPOSITORY_TYPE_GIT => 'DiffusionGitRequest',
+ PhabricatorRepositoryType::REPOSITORY_TYPE_SVN => 'DiffusionSvnRequest',
+ PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL =>
+ 'DiffusionMercurialRequest',
+ );
+
+ $class = idx($map, $repository->getVersionControlSystem());
+
+ if (!$class) {
+ throw new Exception("Unknown version control system!");
}
$object = new $class();
- $object->callsign = $callsign;
$object->repository = $repository;
- $object->line = idx($data, 'line');
- $object->commit = idx($data, 'commit');
- $object->path = idx($data, 'path');
-
- $object->initializeFromAphrontRequestDictionary($data);
+ $object->callsign = $repository->getCallsign();
return $object;
}
- protected function initializeFromAphrontRequestDictionary(array $data) {
- }
+ /**
+ * Internal. Use @{method:newFromDictionary}, not this method.
+ *
+ * @param map Map of parsed data.
+ * @return void
+ * @task new
+ */
+ final private function initializeFromDictionary(array $data) {
+ $this->path = idx($data, 'path');
+ $this->commit = idx($data, 'commit');
+ $this->line = idx($data, 'line');
- protected function parsePath($path) {
- $this->path = $path;
+ if ($this->getSupportsBranches()) {
+ $this->branch = idx($data, 'branch');
+ }
+
+ $this->didInitialize();
}
+
public function getRepository() {
return $this->repository;
}
public function getCallsign() {
return $this->callsign;
}
public function getPath() {
return $this->path;
}
- public function getUriPath() {
- return '/diffusion/'.$this->getCallsign().'/browse/'.$this->path;
- }
-
public function getLine() {
return $this->line;
}
public function getCommit() {
return $this->commit;
}
public function getBranch() {
return $this->branch;
}
public function loadCommit() {
if (empty($this->repositoryCommit)) {
$repository = $this->getRepository();
$commit = id(new PhabricatorRepositoryCommit())->loadOneWhere(
'repositoryID = %d AND commitIdentifier = %s',
$repository->getID(),
$this->getCommit());
$this->repositoryCommit = $commit;
}
return $this->repositoryCommit;
}
public function loadCommitData() {
if (empty($this->repositoryCommitData)) {
$commit = $this->loadCommit();
$data = id(new PhabricatorRepositoryCommitData())->loadOneWhere(
'commitID = %d',
$commit->getID());
if (!$data) {
$data = new PhabricatorRepositoryCommitData();
$data->setCommitMessage('(This commit has not fully parsed yet.)');
}
$this->repositoryCommitData = $data;
}
return $this->repositoryCommitData;
}
/**
* Retrieve a stable, permanent commit name. This returns a non-symbolic
* identifier for the current commit: e.g., a specific commit hash in git
* (NOT a symbolic name like "origin/master") or a specific revision number
* in SVN (NOT a symbolic name like "HEAD").
*
* @return string Stable commit name, like a git hash or SVN revision. Not
* a symbolic commit reference.
*/
public function getStableCommitName() {
return $this->stableCommitName;
}
final public function getRawCommit() {
return $this->commit;
}
public function setCommit($commit) {
$this->commit = $commit;
return $this;
}
- public function getCommitURIComponent($commit) {
- return $commit;
+/* -( Managing Diffusion URIs )-------------------------------------------- */
+
+
+ /**
+ * Generate a Diffusion URI using this request to provide defaults. See
+ * @{method:generateDiffusionURI} for details. This method is the same, but
+ * preserves the request parameters if they are not overridden.
+ *
+ * @param map See @{method:generateDiffusionURI}.
+ * @return PhutilURI Generated URI.
+ * @task uri
+ */
+ public function generateURI(array $params) {
+ if (empty($params['stable'])) {
+ $default_commit = $this->getRawCommit();
+ } else {
+ $default_commit = $this->getStableCommitName();
+ }
+
+ $params += array(
+ 'callsign' => $this->getCallsign(),
+ 'path' => $this->getPath(),
+ 'branch' => $this->getBranch(),
+ 'commit' => $default_commit,
+ );
+ return self::generateDiffusionURI($params);
+ }
+
+
+ /**
+ * Generate a Diffusion URI from a parameter map. Applies the correct encoding
+ * and formatting to the URI. Parameters are:
+ *
+ * - `action` One of `history`, `browse`, `change`, `lastmodified`,
+ * `branch` or `revision-ref`. The action specified by the URI.
+ * - `callsign` Repository callsign.
+ * - `branch` Optional if action is not `branch`, branch name.
+ * - `path` Optional, path to file.
+ * - `commit` Optional, commit identifier.
+ * - `line` Optional, line range.
+ * - `params` Optional, query parameters.
+ *
+ * The function generates the specified URI and returns it.
+ *
+ * @param map See documentation.
+ * @return PhutilURI Generated URI.
+ * @task uri
+ */
+ public static function generateDiffusionURI(array $params) {
+ $action = idx($params, 'action');
+
+ $callsign = idx($params, 'callsign');
+ $path = idx($params, 'path');
+ $branch = idx($params, 'branch');
+ $commit = idx($params, 'commit');
+ $line = idx($params, 'line');
+
+ if (strlen($callsign)) {
+ $callsign = phutil_escape_uri_path_component($callsign).'/';
+ }
+
+ if (strlen($branch)) {
+ $branch = phutil_escape_uri_path_component($branch).'/';
+ }
+
+ if (strlen($path)) {
+ $path = str_replace(array(';', '$'), array(';;', '$$'), $path);
+ $path = phutil_escape_uri($path);
+ }
+
+ $path = "{$branch}{$path}";
+
+ if (strlen($commit)) {
+ $commit = ';'.phutil_escape_uri($commit);
+ }
+
+ if (strlen($line)) {
+ $line = '$'.phutil_escape_uri($line);
+ }
+
+ $req_callsign = false;
+ $req_branch = false;
+
+ switch ($action) {
+ case 'history':
+ case 'browse':
+ case 'change':
+ case 'lastmodified':
+ $req_callsign = true;
+ break;
+ case 'branch':
+ $req_callsign = true;
+ $req_branch = true;
+ break;
+ }
+
+ if ($req_callsign && !strlen($callsign)) {
+ throw new Exception(
+ "Diffusion URI action '{$action}' requires callsign!");
+ }
+
+ if ($req_branch && !strlen($branch)) {
+ throw new Exception(
+ "Diffusion URI action '{$action}' requires brnach!");
+ }
+
+ switch ($action) {
+ case 'change':
+ case 'history':
+ case 'browse':
+ case 'lastmodified':
+ $uri = "/diffusion/{$callsign}{$action}/{$path}{$commit}{$line}";
+ break;
+ case 'branch':
+ $uri = "/diffusion/{$callsign}repository/{$path}";
+ break;
+ case 'rendering-ref':
+ // This isn't a real URI per se, it's passed as a query parameter to
+ // the ajax changeset stuff but then we parse it back out as though
+ // it came from a URI.
+ $uri = "{$path}{$commit}";
+ break;
+ default:
+ throw new Exception("Unknown Diffusion URI action '{$action}'!");
+ }
+
+ if ($action == 'rendering-ref') {
+ return $uri;
+ }
+
+ $uri = new PhutilURI($uri);
+ if (idx($params, 'params')) {
+ $uri->setQueryParams($params['params']);
+ }
+
+ return $uri;
}
- public function getBranchURIComponent($branch) {
- return $branch;
+
+ /**
+ * Internal. Public only for unit tests.
+ *
+ * Parse the request URI into components.
+ *
+ * @param string URI blob.
+ * @param bool True if this VCS supports branches.
+ * @return map Parsed URI.
+ *
+ * @task uri
+ */
+ public static function parseRequestBlob($blob, $supports_branches) {
+ $result = array(
+ 'branch' => null,
+ 'path' => null,
+ 'commit' => null,
+ 'line' => null,
+ );
+
+ $matches = null;
+
+ if ($supports_branches) {
+ // Consume the front part of the URI, up to the first "/". This is the
+ // path-component encoded branch name.
+ if (preg_match('@^([^/]+)/@', $blob, $matches)) {
+ $result['branch'] = phutil_unescape_uri_path_component($matches[1]);
+ $blob = substr($blob, strlen($matches[1]) + 1);
+ }
+ }
+
+ // Consume the back part of the URI, up to the first "$". Use a negative
+ // lookbehind to prevent matching '$$'. We double the '$' symbol when
+ // encoding so that files with names like "money/$100" will survive.
+ if (preg_match('@(?<![$])[$]([\d-]+)$@', $blob, $matches)) {
+ $result['line'] = $matches[1];
+ $blob = substr($blob, 0, -(strlen($matches[1]) + 1));
+ }
+
+ // Consume the commit name, stopping on ';;'.
+ if (preg_match('@(?<!;);([a-z0-9]+)$@', $blob, $matches)) {
+ $result['commit'] = $matches[1];
+ $blob = substr($blob, 0, -(strlen($matches[1]) + 1));
+ }
+
+ // Un-double our delimiter characters.
+ if (strlen($blob)) {
+ $result['path'] = str_replace(array(';;', '$$'), array(';', '$'), $blob);
+ }
+
+ $parts = explode('/', $result['path']);
+ foreach ($parts as $part) {
+ // Prevent any hyjinx since we're ultimately shipping this to the
+ // filesystem under a lot of workflows.
+ if ($part == '..') {
+ throw new Exception("Invalid path URI.");
+ }
+ }
+
+ return $result;
}
}
diff --git a/src/applications/diffusion/request/base/__init__.php b/src/applications/diffusion/request/base/__init__.php
index 0439ae99df..55d28e7536 100644
--- a/src/applications/diffusion/request/base/__init__.php
+++ b/src/applications/diffusion/request/base/__init__.php
@@ -1,17 +1,19 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/repository/constants/repositorytype');
phutil_require_module('phabricator', 'applications/repository/storage/commit');
phutil_require_module('phabricator', 'applications/repository/storage/commitdata');
phutil_require_module('phabricator', 'applications/repository/storage/repository');
+phutil_require_module('phutil', 'markup');
+phutil_require_module('phutil', 'parser/uri');
phutil_require_module('phutil', 'utils');
phutil_require_source('DiffusionRequest.php');
diff --git a/src/applications/diffusion/request/base/__tests__/DiffusionURITestCase.php b/src/applications/diffusion/request/base/__tests__/DiffusionURITestCase.php
new file mode 100644
index 0000000000..14d3e8040c
--- /dev/null
+++ b/src/applications/diffusion/request/base/__tests__/DiffusionURITestCase.php
@@ -0,0 +1,137 @@
+<?php
+
+/*
+ * Copyright 2012 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+final class DiffusionURITestCase extends ArcanistPhutilTestCase {
+
+ public function testBlobDecode() {
+ $map = array(
+ // This is a basic blob.
+ 'branch/path.ext;abc$3' => array(
+ 'branch' => 'branch',
+ 'path' => 'path.ext',
+ 'commit' => 'abc',
+ 'line' => '3',
+ ),
+ 'branch/path.ext$3' => array(
+ 'branch' => 'branch',
+ 'path' => 'path.ext',
+ 'line' => '3',
+ ),
+ 'branch/money;;/$$100' => array(
+ 'branch' => 'branch',
+ 'path' => 'money;/$100',
+ ),
+ 'a%252Fb/' => array(
+ 'branch' => 'a/b',
+ ),
+ );
+
+ foreach ($map as $input => $expect) {
+
+ // Simulate decode effect of the webserver.
+ $input = rawurldecode($input);
+
+ $expect = $expect + array(
+ 'branch' => null,
+ 'path' => null,
+ 'commit' => null,
+ 'line' => null,
+ );
+ $expect = array_select_keys(
+ $expect,
+ array('branch', 'path', 'commit', 'line'));
+
+ $actual = $this->parseBlob($input);
+
+ $this->assertEqual(
+ $expect,
+ $actual,
+ "Parsing '{$input}'");
+ }
+ }
+
+ public function testBlobDecodeFail() {
+ $this->tryTestCaseMap(
+ array(
+ 'branch/path/../../../secrets/secrets.key' => false,
+ ),
+ array($this, 'parseBlob'));
+ }
+
+ public function parseBlob($blob) {
+ return DiffusionRequest::parseRequestBlob(
+ $blob,
+ $supports_branches = true);
+ }
+
+ public function testURIGeneration() {
+ $map = array(
+ '/diffusion/A/browse/branch/path.ext;abc$1' => array(
+ 'action' => 'browse',
+ 'callsign' => 'A',
+ 'branch' => 'branch',
+ 'path' => 'path.ext',
+ 'commit' => 'abc',
+ 'line' => '1',
+ ),
+ '/diffusion/A/browse/a%252Fb/path.ext' => array(
+ 'action' => 'browse',
+ 'callsign' => 'A',
+ 'branch' => 'a/b',
+ 'path' => 'path.ext',
+ ),
+ '/diffusion/A/browse/%2B/%20%21' => array(
+ 'action' => 'browse',
+ 'callsign' => 'A',
+ 'path' => '+/ !',
+ ),
+ '/diffusion/A/browse/money/%24%24100$2' => array(
+ 'action' => 'browse',
+ 'callsign' => 'A',
+ 'path' => 'money/$100',
+ 'line' => '2',
+ ),
+ '/diffusion/A/browse/path/to/file.ext?view=things' => array(
+ 'action' => 'browse',
+ 'callsign' => 'A',
+ 'path' => 'path/to/file.ext',
+ 'params' => array(
+ 'view' => 'things',
+ ),
+ ),
+ '/diffusion/A/repository/master/' => array(
+ 'action' => 'branch',
+ 'callsign' => 'A',
+ 'branch' => 'master',
+ ),
+ 'path/to/file.ext;abc' => array(
+ 'action' => 'rendering-ref',
+ 'path' => 'path/to/file.ext',
+ 'commit' => 'abc',
+ ),
+ );
+
+ foreach ($map as $expect => $input) {
+ $actual = DiffusionRequest::generateDiffusionURI($input);
+ $this->assertEqual(
+ $expect,
+ (string)$actual);
+ }
+ }
+
+}
diff --git a/src/applications/diffusion/request/base/__tests__/__init__.php b/src/applications/diffusion/request/base/__tests__/__init__.php
new file mode 100644
index 0000000000..7ce064365b
--- /dev/null
+++ b/src/applications/diffusion/request/base/__tests__/__init__.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('arcanist', 'unit/engine/phutil/testcase');
+
+phutil_require_module('phabricator', 'applications/diffusion/request/base');
+
+phutil_require_module('phutil', 'utils');
+
+
+phutil_require_source('DiffusionURITestCase.php');
diff --git a/src/applications/diffusion/request/git/DiffusionGitRequest.php b/src/applications/diffusion/request/git/DiffusionGitRequest.php
index 71c14eefc7..6cd359655d 100644
--- a/src/applications/diffusion/request/git/DiffusionGitRequest.php
+++ b/src/applications/diffusion/request/git/DiffusionGitRequest.php
@@ -1,151 +1,111 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+/**
+ * @group diffusion
+ */
final class DiffusionGitRequest extends DiffusionRequest {
- protected function initializeFromAphrontRequestDictionary(array $data) {
- parent::initializeFromAphrontRequestDictionary($data);
-
- $path = $this->path;
- $parts = explode('/', $path);
-
- $branch = array_shift($parts);
- if ($branch != ':') {
- $this->branch = $this->decodeBranchName($branch);
- }
-
- foreach ($parts as $key => $part) {
- // Prevent any hyjinx since we're ultimately shipping this to the
- // filesystem under a lot of git workflows.
- if ($part == '..') {
- unset($parts[$key]);
- }
- }
-
- $this->path = implode('/', $parts);
+ protected function getSupportsBranches() {
+ return true;
+ }
+ protected function didInitialize() {
if ($this->repository) {
$repository = $this->repository;
// TODO: This is not terribly efficient and does not produce terribly
// good error messages, but it seems better to put error handling code
// here than to try to do it in every query.
$branch = $this->getBranch();
// TODO: Here, particularly, we should give the user a specific error
// message to indicate whether they've typed in some bogus branch and/or
// followed a bad link, or misconfigured the default branch in the
// Repository tool.
list($this->stableCommitName) = $repository->execxLocalCommand(
'rev-parse --verify %s/%s',
DiffusionBranchInformation::DEFAULT_GIT_REMOTE,
$branch);
if ($this->commit) {
list($commit) = $repository->execxLocalCommand(
'rev-parse --verify %s',
$this->commit);
// Beyond verifying them, expand commit short forms to full 40-character
// hashes.
$this->commit = trim($commit);
// If we have a commit, overwrite the branch commit with the more
// specific commit.
$this->stableCommitName = $this->commit;
/*
TODO: Unclear if this is actually a good idea or not; it breaks commit views
at the very least.
list($contains) = $repository->execxLocalCommand(
'branch --contains %s',
$this->commit);
$contains = array_filter(explode("\n", $contains));
$found = false;
foreach ($contains as $containing_branch) {
$containing_branch = trim($containing_branch, "* \n");
if ($containing_branch == $branch) {
$found = true;
break;
}
}
if (!$found) {
throw new Exception(
"Commit does not exist on this branch!");
}
*/
}
}
}
public function getBranch() {
if ($this->branch) {
return $this->branch;
}
if ($this->repository) {
return $this->repository->getDetail('default-branch', 'master');
}
throw new Exception("Unable to determine branch!");
}
- public function getUriPath() {
- return '/diffusion/'.$this->getCallsign().'/browse/'.
- $this->getBranchURIComponent($this->branch).$this->path;
- }
-
public function getCommit() {
if ($this->commit) {
return $this->commit;
}
$remote = DiffusionBranchInformation::DEFAULT_GIT_REMOTE;
return $remote.'/'.$this->getBranch();
}
public function getStableCommitName() {
return substr($this->stableCommitName, 0, 16);
}
- public function getBranchURIComponent($branch) {
- return $this->encodeBranchName($branch).'/';
- }
-
- private function decodeBranchName($branch) {
- $branch = str_replace(':', '/', $branch);
-
- // Backward compatibility for older-style URIs which had an explicit
- // "origin" remote in the branch name. If a remote is specified, strip it
- // away.
- if (strpos($branch, '/') !== false) {
- $parts = explode('/', $branch);
- $branch = end($parts);
- }
-
- return $branch;
- }
-
- private function encodeBranchName($branch) {
- return str_replace('/', ':', $branch);
- }
-
}
diff --git a/src/applications/diffusion/request/mercurial/DiffusionMercurialRequest.php b/src/applications/diffusion/request/mercurial/DiffusionMercurialRequest.php
index 77e9334bf2..59f1833007 100644
--- a/src/applications/diffusion/request/mercurial/DiffusionMercurialRequest.php
+++ b/src/applications/diffusion/request/mercurial/DiffusionMercurialRequest.php
@@ -1,81 +1,53 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// TODO: This has some minor code duplication vs the Git request that could be
-// shared.
+/**
+ * @group diffusion
+ */
final class DiffusionMercurialRequest extends DiffusionRequest {
- protected function initializeFromAphrontRequestDictionary(array $data) {
- parent::initializeFromAphrontRequestDictionary($data);
-
- $path = $this->path;
- $parts = explode('/', $path);
-
- $branch = array_shift($parts);
- if ($branch != ':') {
- $this->branch = $this->decodeBranchName($branch);
- }
-
- foreach ($parts as $key => $part) {
- if ($part == '..') {
- unset($parts[$key]);
- }
- }
+ protected function getSupportsBranches() {
+ return true;
+ }
- $this->path = implode('/', $parts);
+ protected function didInitialize() {
+ return;
}
public function getBranch() {
if ($this->branch) {
return $this->branch;
}
if ($this->repository) {
return $this->repository->getDetail('default-branch', 'default');
}
throw new Exception("Unable to determine branch!");
}
- public function getUriPath() {
- return '/diffusion/'.$this->getCallsign().'/browse/'.
- $this->getBranchURIComponent($this->branch).$this->path;
- }
-
public function getCommit() {
if ($this->commit) {
return $this->commit;
}
return $this->getBranch();
}
public function getStableCommitName() {
return substr($this->stableCommitName, 0, 16);
}
- public function getBranchURIComponent($branch) {
- return $this->encodeBranchName($branch).'/';
- }
-
- private function decodeBranchName($branch) {
- return str_replace(':', '/', $branch);
- }
-
- private function encodeBranchName($branch) {
- return str_replace('/', ':', $branch);
- }
-
}
diff --git a/src/applications/diffusion/request/svn/DiffusionSvnRequest.php b/src/applications/diffusion/request/svn/DiffusionSvnRequest.php
index eb1c19c210..315c2f1a0b 100644
--- a/src/applications/diffusion/request/svn/DiffusionSvnRequest.php
+++ b/src/applications/diffusion/request/svn/DiffusionSvnRequest.php
@@ -1,67 +1,67 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+/**
+ * @group diffusion
+ */
final class DiffusionSvnRequest extends DiffusionRequest {
- protected function initializeFromAphrontRequestDictionary(array $data) {
- parent::initializeFromAphrontRequestDictionary($data);
+ protected function getSupportsBranches() {
+ return false;
+ }
+ protected function didInitialize() {
if ($this->path === null) {
$subpath = $this->repository->getDetail('svn-subpath');
if ($subpath) {
$this->path = $subpath;
}
}
-
- if (!strncmp($this->path, ':', 1)) {
- $this->path = substr($this->path, 1);
- $this->path = ltrim($this->path, '/');
- }
}
public function getStableCommitName() {
if ($this->commit) {
return $this->commit;
}
if ($this->stableCommitName === null) {
$commit = id(new PhabricatorRepositoryCommit())
->loadOneWhere(
'repositoryID = %d ORDER BY epoch DESC LIMIT 1',
$this->getRepository()->getID());
if ($commit) {
$this->stableCommitName = $commit->getCommitIdentifier();
} else {
// For new repositories, we may not have parsed any commits yet. Call
// the stable commit "1" and avoid fataling.
$this->stableCommitName = 1;
}
}
return $this->stableCommitName;
}
public function getCommit() {
if ($this->commit) {
return $this->commit;
}
return $this->getStableCommitName();
}
}
diff --git a/src/applications/diffusion/view/base/DiffusionView.php b/src/applications/diffusion/view/base/DiffusionView.php
index 53973f0389..223844c563 100644
--- a/src/applications/diffusion/view/base/DiffusionView.php
+++ b/src/applications/diffusion/view/base/DiffusionView.php
@@ -1,146 +1,119 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
abstract class DiffusionView extends AphrontView {
private $diffusionRequest;
final public function setDiffusionRequest(DiffusionRequest $request) {
$this->diffusionRequest = $request;
return $this;
}
final public function getDiffusionRequest() {
return $this->diffusionRequest;
}
final public function linkChange($change_type, $file_type, $path = null,
$commit_identifier = null) {
$text = DifferentialChangeType::getFullNameForChangeType($change_type);
if ($change_type == DifferentialChangeType::TYPE_CHILD) {
// TODO: Don't link COPY_AWAY without a direct change.
return $text;
}
if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
return $text;
}
- $drequest = $this->getDiffusionRequest();
-
- if ($commit_identifier) {
- $commit = ';'.$commit_identifier;
- } else if ($drequest->getRawCommit()) {
- $commit = ';'.$drequest->getCommitURIComponent($drequest->getRawCommit());
- } else {
- $commit = null;
- }
-
- $repository = $drequest->getRepository();
- $callsign = $repository->getCallsign();
-
- $branch = $drequest->getBranchURIComponent($drequest->getBranch());
- $path = $branch.($path ? $path : $drequest->getPath());
+ $href = $this->getDiffusionRequest()->generateURI(
+ array(
+ 'action' => 'change',
+ 'path' => $path,
+ 'commit' => $commit_identifier,
+ ));
return phutil_render_tag(
'a',
array(
- 'href' => "/diffusion/{$callsign}/change/{$path}{$commit}",
+ 'href' => $href,
),
$text);
}
final public function linkHistory($path) {
- $drequest = $this->getDiffusionRequest();
-
- if ($drequest->getRawCommit()) {
- $commit = ';'.$drequest->getCommitURIComponent($drequest->getRawCommit());
- } else {
- $commit = null;
- }
-
- $repository = $drequest->getRepository();
- $callsign = $repository->getCallsign();
-
- $branch = $drequest->getBranchURIComponent($drequest->getBranch());
- $path = $branch.$path;
-
- $text = 'History';
+ $href = $this->getDiffusionRequest()->generateURI(
+ array(
+ 'action' => 'history',
+ 'path' => $path,
+ ));
return phutil_render_tag(
'a',
array(
- 'href' => "/diffusion/{$callsign}/history/{$path}{$commit}",
+ 'href' => $href,
),
- $text);
+ 'History');
}
final public function linkBrowse($path, array $details = array()) {
- $drequest = $this->getDiffusionRequest();
- $raw_commit = idx($details, 'commit', $drequest->getRawCommit());
- if ($raw_commit) {
- $commit = ';'.$drequest->getCommitURIComponent($raw_commit);
- } else {
- $commit = null;
- }
-
- $repository = $drequest->getRepository();
- $callsign = $repository->getCallsign();
-
- $branch = $drequest->getBranchURIComponent($drequest->getBranch());
- $path = $branch.$path;
+ $href = $this->getDiffusionRequest()->generateURI(
+ array(
+ 'action' => 'browse',
+ 'path' => $path,
+ ));
if (isset($details['text'])) {
$text = phutil_escape_html($details['text']);
} else {
$text = 'Browse';
}
return phutil_render_tag(
'a',
array(
- 'href' => "/diffusion/{$callsign}/browse/{$path}{$commit}",
+ 'href' => $href,
),
$text);
}
final public static function linkCommit($repository, $commit) {
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$commit_name = substr($commit, 0, 12);
break;
default:
$commit_name = $commit;
break;
}
$callsign = $repository->getCallsign();
$commit_name = "r{$callsign}{$commit_name}";
return phutil_render_tag(
'a',
array(
'href' => "/r{$callsign}{$commit}",
),
$commit_name);
}
}
diff --git a/src/applications/diffusion/view/base/__init__.php b/src/applications/diffusion/view/base/__init__.php
index 8db5411a0f..0e55875327 100644
--- a/src/applications/diffusion/view/base/__init__.php
+++ b/src/applications/diffusion/view/base/__init__.php
@@ -1,17 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/differential/constants/changetype');
phutil_require_module('phabricator', 'applications/repository/constants/repositorytype');
phutil_require_module('phabricator', 'view/base');
phutil_require_module('phutil', 'markup');
-phutil_require_module('phutil', 'utils');
phutil_require_source('DiffusionView.php');
diff --git a/src/applications/diffusion/view/branchtable/DiffusionBranchTableView.php b/src/applications/diffusion/view/branchtable/DiffusionBranchTableView.php
index c178454253..c998e0b089 100644
--- a/src/applications/diffusion/view/branchtable/DiffusionBranchTableView.php
+++ b/src/applications/diffusion/view/branchtable/DiffusionBranchTableView.php
@@ -1,72 +1,72 @@
<?php
/*
- * Copyright 2011 Facebook, Inc.
+ * Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DiffusionBranchTableView extends DiffusionView {
private $branches;
public function setBranches(array $branches) {
$this->branches = $branches;
return $this;
}
public function render() {
$drequest = $this->getDiffusionRequest();
$current_branch = $drequest->getBranch();
- $callsign = $drequest->getRepository()->getCallsign();
-
$rows = array();
$rowc = array();
foreach ($this->branches as $branch) {
- $branch_uri = $drequest->getBranchURIComponent($branch->getName());
-
$rows[] = array(
phutil_render_tag(
'a',
array(
- 'href' => "/diffusion/{$callsign}/repository/{$branch_uri}",
+ 'href' => $drequest->generateURI(
+ array(
+ 'action' => 'branch',
+ 'branch' => $branch->getName(),
+ )),
),
phutil_escape_html($branch->getName())),
self::linkCommit(
$drequest->getRepository(),
$branch->getHeadCommitIdentifier()),
// TODO: etc etc
);
if ($branch->getName() == $current_branch) {
$rowc[] = 'highlighted';
} else {
$rowc[] = null;
}
}
$view = new AphrontTableView($rows);
$view->setHeaders(
array(
'Branch',
'Head',
));
$view->setColumnClasses(
array(
'wide',
));
$view->setRowClasses($rowc);
return $view->render();
}
}
diff --git a/src/applications/diffusion/view/browsetable/DiffusionBrowseTableView.php b/src/applications/diffusion/view/browsetable/DiffusionBrowseTableView.php
index 84bddf952b..1ec8f279f5 100644
--- a/src/applications/diffusion/view/browsetable/DiffusionBrowseTableView.php
+++ b/src/applications/diffusion/view/browsetable/DiffusionBrowseTableView.php
@@ -1,175 +1,175 @@
<?php
/*
- * Copyright 2011 Facebook, Inc.
+ * Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DiffusionBrowseTableView extends DiffusionView {
private $paths;
private $handles = array();
public function setPaths(array $paths) {
$this->paths = $paths;
return $this;
}
public function setHandles(array $handles) {
$this->handles = $handles;
return $this;
}
public static function renderLastModifiedColumns(
PhabricatorRepository $repository,
array $handles,
PhabricatorRepositoryCommit $commit = null,
PhabricatorRepositoryCommitData $data = null) {
if ($commit) {
$epoch = $commit->getEpoch();
$modified = DiffusionView::linkCommit(
$repository,
$commit->getCommitIdentifier());
$date = date('M j, Y', $epoch);
$time = date('g:i A', $epoch);
} else {
$modified = '';
$date = '';
$time = '';
}
if ($data) {
$author_phid = $data->getCommitDetail('authorPHID');
if ($author_phid && isset($handles[$author_phid])) {
$author = $handles[$author_phid]->renderLink();
} else {
$author = phutil_escape_html($data->getAuthorName());
}
$details = AphrontTableView::renderSingleDisplayLine(
phutil_escape_html($data->getSummary()));
} else {
$author = '';
$details = '';
}
return array(
'commit' => $modified,
'date' => $date,
'time' => $time,
'author' => $author,
'details' => $details,
);
}
public function render() {
$request = $this->getDiffusionRequest();
$repository = $request->getRepository();
$base_path = trim($request->getPath(), '/');
if ($base_path) {
$base_path = $base_path.'/';
}
$need_pull = array();
$rows = array();
foreach ($this->paths as $path) {
if ($path->getFileType() == DifferentialChangeType::FILE_DIRECTORY) {
$browse_text = $path->getPath().'/';
$dir_slash = '/';
$browse_link = '<strong>'.$this->linkBrowse(
$base_path.$path->getPath().$dir_slash,
array(
'text' => $browse_text,
)).'</strong>';
} else {
$browse_text = $path->getPath();
$dir_slash = null;
$browse_link = $this->linkBrowse(
$base_path.$path->getPath().$dir_slash,
array(
'text' => $browse_text,
));
}
$commit = $path->getLastModifiedCommit();
if ($commit) {
$dict = self::renderLastModifiedColumns(
$repository,
$this->handles,
$commit,
$path->getLastCommitData());
} else {
$dict = array(
'commit' => celerity_generate_unique_node_id(),
'date' => celerity_generate_unique_node_id(),
'time' => celerity_generate_unique_node_id(),
'author' => celerity_generate_unique_node_id(),
'details' => celerity_generate_unique_node_id(),
);
- $uri =
- '/diffusion/'.$repository->getCallsign().'/lastmodified/'.
- $request->getBranchURIComponent($request->getBranch()).
- $base_path.$path->getPath();
- if ($request->getRawCommit()) {
- $uri .= ';'.$request->getRawCommit();
- }
+
+ $uri = (string)$request->generateURI(
+ array(
+ 'action' => 'lastmodified',
+ 'path' => $base_path.$path->getPath(),
+ ));
+
$need_pull[$uri] = $dict;
foreach ($dict as $k => $uniq) {
$dict[$k] = '<span id="'.$uniq.'"></span>';
}
}
$rows[] = array(
$this->linkHistory($base_path.$path->getPath().$dir_slash),
$browse_link,
$dict['commit'],
$dict['date'],
$dict['time'],
$dict['author'],
$dict['details'],
);
}
if ($need_pull) {
Javelin::initBehavior('diffusion-pull-lastmodified', $need_pull);
}
$view = new AphrontTableView($rows);
$view->setHeaders(
array(
'History',
'Path',
'Modified',
'Date',
'Time',
'Author',
'Details',
));
$view->setColumnClasses(
array(
'',
'',
'',
'',
'right',
'',
'wide',
));
return $view->render();
}
}
diff --git a/src/applications/owners/query/path/PhabricatorOwnerPathQuery.php b/src/applications/owners/query/path/PhabricatorOwnerPathQuery.php
index 7551f800c6..7bcf74c612 100644
--- a/src/applications/owners/query/path/PhabricatorOwnerPathQuery.php
+++ b/src/applications/owners/query/path/PhabricatorOwnerPathQuery.php
@@ -1,52 +1,46 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class PhabricatorOwnerPathQuery {
public static function loadAffectedPaths(
PhabricatorRepository $repository,
PhabricatorRepositoryCommit $commit) {
- $drequest = self::buildDiffusionRequest($repository, $commit);
+ $drequest = DiffusionRequest::newFromAphrontRequestDictionary(
+ array(
+ 'repository' => $repository,
+ 'commit' => $commit->getCommitIdentifier(),
+ ));
+
$path_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
$drequest);
$paths = $path_query->loadChanges();
$result = array();
foreach ($paths as $path) {
$basic_path = '/' . $path->getPath();
if ($path->getFileType() == DifferentialChangeType::FILE_DIRECTORY) {
$basic_path = rtrim($basic_path, '/') . '/';
}
$result[] = $basic_path;
}
return $result;
}
- private static function buildDiffusionRequest(
- PhabricatorRepository $repository,
- PhabricatorRepositoryCommit $commit) {
-
- return DiffusionRequest::newFromAphrontRequestDictionary(
- array(
- 'callsign' => $repository->getCallsign(),
- 'commit' => $commit->getCommitIdentifier(),
- ));
- }
-
}
diff --git a/src/applications/owners/storage/package/PhabricatorOwnersPackage.php b/src/applications/owners/storage/package/PhabricatorOwnersPackage.php
index 17d1941b49..209a367966 100644
--- a/src/applications/owners/storage/package/PhabricatorOwnersPackage.php
+++ b/src/applications/owners/storage/package/PhabricatorOwnersPackage.php
@@ -1,254 +1,254 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class PhabricatorOwnersPackage extends PhabricatorOwnersDAO {
protected $phid;
protected $name;
protected $auditingEnabled;
protected $description;
protected $primaryOwnerPHID;
private $unsavedOwners;
private $unsavedPaths;
public function getConfiguration() {
return array(
// This information is better available from the history table.
self::CONFIG_TIMESTAMPS => false,
self::CONFIG_AUX_PHID => true,
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID('OPKG');
}
public function attachUnsavedOwners(array $owners) {
$this->unsavedOwners = $owners;
return $this;
}
public function attachUnsavedPaths(array $paths) {
$this->unsavedPaths = $paths;
return $this;
}
public function loadOwners() {
if (!$this->getID()) {
return array();
}
return id(new PhabricatorOwnersOwner())->loadAllWhere(
'packageID = %d',
$this->getID());
}
public function loadPaths() {
if (!$this->getID()) {
return array();
}
return id(new PhabricatorOwnersPath())->loadAllWhere(
'packageID = %d',
$this->getID());
}
public static function loadAffectedPackages(
PhabricatorRepository $repository,
array $paths) {
if (!$paths) {
return array();
}
$fragments = array(
'/' => true,
);
foreach ($paths as $path) {
$fragments += self::splitPath($path);
}
return self::loadPackagesForPaths($repository, array_keys($fragments));
}
public static function loadOwningPackages($repository, $path) {
if (empty($path)) {
return array();
}
$fragments = self::splitPath($path);
return self::loadPackagesForPaths($repository, array_keys($fragments), 1);
}
private static function loadPackagesForPaths(
PhabricatorRepository $repository,
array $paths,
$limit = 0) {
$package = new PhabricatorOwnersPackage();
$path = new PhabricatorOwnersPath();
$conn = $package->establishConnection('r');
$repository_clause = qsprintf($conn, 'AND p.repositoryPHID = %s',
$repository->getPHID());
$limit_clause = '';
if (!empty($limit)) {
$limit_clause = qsprintf($conn, 'LIMIT %d', $limit);
}
$data = queryfx_all(
$conn,
'SELECT pkg.id FROM %T pkg JOIN %T p ON p.packageID = pkg.id
WHERE p.path IN (%Ls) %Q ORDER BY LENGTH(p.path) DESC %Q',
$package->getTableName(),
$path->getTableName(),
$paths,
$repository_clause,
$limit_clause);
$ids = ipull($data, 'id');
if (empty($ids)) {
return array();
}
$order = array();
foreach ($ids as $id) {
if (empty($order[$id])) {
$order[$id] = true;
}
}
$packages = $package->loadAllWhere('id in (%Ld)', array_keys($order));
$packages = array_select_keys($packages, array_keys($order));
return $packages;
}
public function save() {
// TODO: Transactions!
$ret = parent::save();
if ($this->unsavedOwners) {
$new_owners = array_fill_keys($this->unsavedOwners, true);
$cur_owners = array();
foreach ($this->loadOwners() as $owner) {
if (empty($new_owners[$owner->getUserPHID()])) {
$owner->delete();
continue;
}
$cur_owners[$owner->getUserPHID()] = true;
}
$add_owners = array_diff_key($new_owners, $cur_owners);
foreach ($add_owners as $phid => $ignored) {
$owner = new PhabricatorOwnersOwner();
$owner->setPackageID($this->getID());
$owner->setUserPHID($phid);
$owner->save();
}
unset($this->unsavedOwners);
}
if ($this->unsavedPaths) {
$new_paths = igroup($this->unsavedPaths, 'repositoryPHID', 'path');
$cur_paths = $this->loadPaths();
foreach ($cur_paths as $key => $path) {
if (empty($new_paths[$path->getRepositoryPHID()][$path->getPath()])) {
$path->delete();
unset($cur_paths[$key]);
}
}
$cur_paths = mgroup($cur_paths, 'getRepositoryPHID', 'getPath');
foreach ($new_paths as $repository_phid => $paths) {
// get repository object for path validation
$repository = id(new PhabricatorRepository())->loadOneWhere(
'phid = %s',
$repository_phid);
if (!$repository) {
continue;
}
foreach ($paths as $path => $ignored) {
$path = ltrim($path, '/');
// build query to validate path
- $drequest = DiffusionRequest::newFromAphrontRequestDictionary(
+ $drequest = DiffusionRequest::newFromDictionary(
array(
- 'callsign' => $repository->getCallsign(),
- 'path' => ':/'.$path,
+ 'repository' => $repository,
+ 'path' => $path,
));
$query = DiffusionBrowseQuery::newFromDiffusionRequest($drequest);
$query->needValidityOnly(true);
$valid = $query->loadPaths();
$is_directory = true;
if (!$valid) {
switch ($query->getReasonForEmptyResultSet()) {
case DiffusionBrowseQuery::REASON_IS_FILE:
$valid = true;
$is_directory = false;
break;
case DiffusionBrowseQuery::REASON_IS_EMPTY:
$valid = true;
break;
}
}
if ($is_directory && substr($path, -1) != '/') {
$path .= '/';
}
if (substr($path, 0, 1) != '/') {
$path = '/'.$path;
}
if (empty($cur_paths[$repository_phid][$path]) && $valid) {
$obj = new PhabricatorOwnersPath();
$obj->setPackageID($this->getID());
$obj->setRepositoryPHID($repository_phid);
$obj->setPath($path);
$obj->save();
}
}
}
unset($this->unsavedPaths);
}
return $ret;
}
public function delete() {
foreach ($this->loadOwners() as $owner) {
$owner->delete();
}
foreach ($this->loadPaths() as $path) {
$path->delete();
}
return parent::delete();
}
private static function splitPath($path) {
$result = array();
$trailing_slash = preg_match('@/$@', $path) ? '/' : '';
$path = trim($path, '/');
$parts = explode('/', $path);
while (count($parts)) {
$result['/'.implode('/', $parts).$trailing_slash] = true;
$trailing_slash = '/';
array_pop($parts);
}
return $result;
}
}
diff --git a/src/applications/repository/storage/symbol/PhabricatorRepositorySymbol.php b/src/applications/repository/storage/symbol/PhabricatorRepositorySymbol.php
index 776810417c..4b5da1b355 100644
--- a/src/applications/repository/storage/symbol/PhabricatorRepositorySymbol.php
+++ b/src/applications/repository/storage/symbol/PhabricatorRepositorySymbol.php
@@ -1,99 +1,94 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Records information about symbol locations in a codebase, like where classes
* and functions are defined.
*
* Query symbols with @{class:DiffusionSymbolQuery}.
*
* @group diffusion
*/
final class PhabricatorRepositorySymbol extends PhabricatorRepositoryDAO {
protected $arcanistProjectID;
protected $symbolName;
protected $symbolType;
protected $symbolLanguage;
protected $pathID;
protected $lineNumber;
private $path = false;
private $arcanistProject = false;
private $repository = false;
public function getConfiguration() {
return array(
self::CONFIG_IDS => self::IDS_MANUAL,
self::CONFIG_TIMESTAMPS => false,
) + parent::getConfiguration();
}
public function getURI() {
- $repo = $this->getRepository();
- $file = $this->getPath();
- $line = $this->getLineNumber();
-
- $drequest = DiffusionRequest::newFromAphrontRequestDictionary(
+ return DiffusionRequest::generateDiffusionURI(
array(
- 'callsign' => $repo->getCallsign(),
+ 'action' => 'browse',
+ 'callsign' => $this->getRepository()->getCallsign(),
+ 'path' => $this->getPath(),
+ 'line' => $this->getLineNumber(),
));
- $branch = $drequest->getBranchURIComponent($drequest->getBranch());
- $file = $branch.ltrim($file, '/');
-
- return '/diffusion/'.$repo->getCallsign().'/browse/'.$file.'$'.$line;
}
public function getPath() {
if ($this->path === false) {
throw new Exception('Call attachPath() before getPath()!');
}
return $this->path;
}
public function attachPath($path) {
$this->path = $path;
return $this;
}
public function getRepository() {
if ($this->repository === false) {
throw new Exception('Call attachRepository() before getRepository()!');
}
return $this->repository;
}
public function attachRepository($repository) {
$this->repository = $repository;
return $this;
}
public function getArcanistProject() {
if ($this->arcanistProject === false) {
throw new Exception(
'Call attachArcanistProject() before getArcanistProject()!');
}
return $this->arcanistProject;
}
public function attachArcanistProject($project) {
$this->arcanistProject = $project;
return $this;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Jan 19 2025, 21:10 (6 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1128789
Default Alt Text
(259 KB)

Event Timeline