Page MenuHomestyx hydra

No OneTemporary

diff --git a/resources/sql/patches/006.repository.sql b/resources/sql/patches/006.repository.sql
new file mode 100644
index 0000000000..569437c2c1
--- /dev/null
+++ b/resources/sql/patches/006.repository.sql
@@ -0,0 +1,42 @@
+create table phabricator_repository.repository_commitdata (
+ id int unsigned not null auto_increment primary key,
+ commitID int unsigned not null,
+ authorName varchar(255) not null,
+ commitMessage longblob not null,
+ unique key (commitID),
+ key (authorName)
+);
+
+ALTER TABLE phabricator_worker.worker_task drop priority;
+ALTER TABLE phabricator_worker.worker_task drop key leaseOwner;
+ALTER TABLE phabricator_worker.worker_task drop key (leaseOwner(16));
+
+create table phabricator_repository.repository_path (
+ id int unsigned not null auto_increment primary key,
+ path varchar(512) not null,
+ unique key (path)
+);
+
+create table phabricator_repository.repository_pathchange (
+ repositoryID int unsigned NOT NULL,
+ pathID int unsigned NOT NULL,
+ commitID int unsigned NOT NULL,
+ targetPathID int unsigned,
+ targetCommitID int unsigned,
+ changeType int unsigned NOT NULL,
+ fileType int unsigned NOT NULL,
+ isDirect bool NOT NULL,
+ commitSequence int unsigned NOT NULL,
+ primary key (commitID, pathID),
+ key (repositoryID, pathID, commitSequence)
+);
+
+create table phabricator_repository.repository_filesystem (
+ repositoryID int unsigned not null,
+ parentID int unsigned not null,
+ svnCommit int unsigned not null,
+ pathID int unsigned not null,
+ existed bool not null,
+ fileType int unsigned not null,
+ primary key (repositoryID, parentID, svnCommit, pathID)
+);
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index 65be1069ec..5eef3533c0 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1,604 +1,628 @@
<?php
/**
* This file is automatically generated. Use 'phutil_mapper.php' to rebuild it.
* @generated
*/
phutil_register_library_map(array(
'class' =>
array(
'Aphront400Response' => 'aphront/response/400',
'Aphront404Response' => 'aphront/response/404',
'AphrontAjaxResponse' => 'aphront/response/ajax',
'AphrontApplicationConfiguration' => 'aphront/applicationconfiguration',
'AphrontController' => 'aphront/controller',
'AphrontDatabaseConnection' => 'storage/connection/base',
'AphrontDefaultApplicationConfiguration' => 'aphront/default/configuration',
'AphrontDefaultApplicationController' => 'aphront/default/controller',
'AphrontDialogResponse' => 'aphront/response/dialog',
'AphrontDialogView' => 'view/dialog',
'AphrontErrorView' => 'view/form/error',
'AphrontException' => 'aphront/exception/base',
'AphrontFileResponse' => 'aphront/response/file',
'AphrontFormCheckboxControl' => 'view/form/control/checkbox',
'AphrontFormControl' => 'view/form/control/base',
'AphrontFormDividerControl' => 'view/form/control/divider',
'AphrontFormFileControl' => 'view/form/control/file',
'AphrontFormMarkupControl' => 'view/form/control/markup',
'AphrontFormPasswordControl' => 'view/form/control/password',
'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',
'AphrontFormTokenizerControl' => 'view/form/control/tokenizer',
'AphrontFormView' => 'view/form/base',
'AphrontHeadsupActionListView' => 'view/layout/headsup/actionlist',
'AphrontHeadsupActionView' => 'view/layout/headsup/action',
'AphrontMySQLDatabaseConnection' => 'storage/connection/mysql',
'AphrontNullView' => 'view/null',
'AphrontPageView' => 'view/page/base',
'AphrontPanelView' => 'view/layout/panel',
'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',
'AphrontRedirectException' => 'aphront/exception/redirect',
'AphrontRedirectResponse' => 'aphront/response/redirect',
'AphrontRequest' => 'aphront/request',
'AphrontRequestFailureView' => 'view/page/failure',
'AphrontResponse' => 'aphront/response/base',
'AphrontSideNavView' => 'view/layout/sidenav',
'AphrontTableView' => 'view/control/table',
'AphrontURIMapper' => 'aphront/mapper',
'AphrontView' => 'view/base',
'AphrontWebpageResponse' => 'aphront/response/webpage',
'CelerityAPI' => 'infrastructure/celerity/api',
'CelerityResourceController' => 'infrastructure/celerity/controller',
'CelerityResourceMap' => 'infrastructure/celerity/map',
'CelerityStaticResourceResponse' => 'infrastructure/celerity/response',
'ConduitAPIMethod' => 'applications/conduit/method/base',
'ConduitAPIRequest' => 'applications/conduit/protocol/request',
'ConduitAPI_conduit_connect_Method' => 'applications/conduit/method/conduit/connect',
'ConduitAPI_conduit_ping_Method' => 'applications/conduit/method/conduit/ping',
'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_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_markcommitted_Method' => 'applications/conduit/method/differential/markcommitted',
'ConduitAPI_differential_parsecommitmessage_Method' => 'applications/conduit/method/differential/parsecommitmessage',
'ConduitAPI_differential_setdiffproperty_Method' => 'applications/conduit/method/differential/setdiffproperty',
'ConduitAPI_differential_updaterevision_Method' => 'applications/conduit/method/differential/updaterevision',
'ConduitAPI_file_upload_Method' => 'applications/conduit/method/file/upload',
'ConduitAPI_user_find_Method' => 'applications/conduit/method/user/find',
'ConduitException' => 'applications/conduit/protocol/exception',
'DarkConsole' => 'aphront/console/api',
'DarkConsoleConfigPlugin' => 'aphront/console/plugin/config',
'DarkConsoleController' => 'aphront/console/controller',
'DarkConsoleCore' => 'aphront/console/core',
'DarkConsoleErrorLogPlugin' => 'aphront/console/plugin/errorlog',
'DarkConsoleErrorLogPluginAPI' => 'aphront/console/plugin/errorlog/api',
'DarkConsolePlugin' => 'aphront/console/plugin/base',
'DarkConsoleRequestPlugin' => 'aphront/console/plugin/request',
'DarkConsoleServicesPlugin' => 'aphront/console/plugin/services',
'DarkConsoleServicesPluginAPI' => 'aphront/console/plugin/services/api',
'DarkConsoleXHProfPlugin' => 'aphront/console/plugin/xhprof',
'DarkConsoleXHProfPluginAPI' => 'aphront/console/plugin/xhprof/api',
'DifferentialAction' => 'applications/differential/constants/action',
'DifferentialAddCommentView' => 'applications/differential/view/addcomment',
'DifferentialAttachController' => 'applications/differential/controller/attach',
'DifferentialCCWelcomeMail' => 'applications/differential/mail/ccwelcome',
'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',
'DifferentialCommitMessage' => 'applications/differential/parser/commitmessage',
'DifferentialCommitMessageData' => 'applications/differential/data/commitmessage',
'DifferentialCommitMessageParserException' => 'applications/differential/parser/commitmessage/exception',
'DifferentialController' => 'applications/differential/controller/base',
'DifferentialDAO' => 'applications/differential/storage/base',
'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',
'DifferentialHunk' => 'applications/differential/storage/hunk',
'DifferentialInlineComment' => 'applications/differential/storage/inlinecomment',
'DifferentialInlineCommentEditController' => 'applications/differential/controller/inlinecommentedit',
'DifferentialInlineCommentPreviewController' => 'applications/differential/controller/inlinecommentpreview',
'DifferentialInlineCommentView' => 'applications/differential/view/inlinecomment',
'DifferentialLintStatus' => 'applications/differential/constants/lintstatus',
'DifferentialMail' => 'applications/differential/mail/base',
'DifferentialMarkupEngineFactory' => 'applications/differential/parser/markup',
'DifferentialNewDiffMail' => 'applications/differential/mail/newdiff',
'DifferentialReviewRequestMail' => 'applications/differential/mail/reviewrequest',
'DifferentialRevision' => 'applications/differential/storage/revision',
'DifferentialRevisionCommentListView' => 'applications/differential/view/revisioncommentlist',
'DifferentialRevisionCommentView' => 'applications/differential/view/revisioncomment',
'DifferentialRevisionControlSystem' => 'applications/differential/constants/revisioncontrolsystem',
'DifferentialRevisionDetailView' => 'applications/differential/view/revisiondetail',
'DifferentialRevisionEditController' => 'applications/differential/controller/revisionedit',
'DifferentialRevisionEditor' => 'applications/differential/editor/revision',
'DifferentialRevisionListController' => 'applications/differential/controller/revisionlist',
'DifferentialRevisionListData' => 'applications/differential/data/revisionlist',
'DifferentialRevisionStatus' => 'applications/differential/constants/revisionstatus',
'DifferentialRevisionUpdateHistoryView' => 'applications/differential/view/revisionupdatehistory',
'DifferentialRevisionViewController' => 'applications/differential/controller/revisionview',
'DifferentialSubscribeController' => 'applications/differential/controller/subscribe',
'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus',
'DiffusionBrowseController' => 'applications/diffusion/controller/browse',
'DiffusionBrowseFileController' => 'applications/diffusion/controller/file',
'DiffusionBrowseQuery' => 'applications/diffusion/query/browse/base',
'DiffusionBrowseTableView' => 'applications/diffusion/view/browsetable',
+ 'DiffusionCommitChangeTableView' => 'applications/diffusion/view/commitchangetable',
+ 'DiffusionCommitController' => 'applications/diffusion/controller/commit',
'DiffusionController' => 'applications/diffusion/controller/base',
'DiffusionFileContent' => 'applications/diffusion/data/filecontent',
'DiffusionFileContentQuery' => 'applications/diffusion/query/filecontent/base',
'DiffusionGitBrowseQuery' => 'applications/diffusion/query/browse/git',
'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/git',
'DiffusionGitHistoryQuery' => 'applications/diffusion/query/history/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',
'DiffusionPathChange' => 'applications/diffusion/data/pathchange',
'DiffusionRepositoryPath' => 'applications/diffusion/data/repositorypath',
'DiffusionRequest' => 'applications/diffusion/request/base',
'Javelin' => 'infrastructure/javelin/api',
'LiskDAO' => 'storage/lisk/dao',
'ManiphestController' => 'applications/maniphest/controller/base',
'ManiphestDAO' => 'applications/maniphest/storage/base',
'ManiphestTask' => 'applications/maniphest/storage/task',
'ManiphestTaskDetailController' => 'applications/maniphest/controller/taskdetail',
'ManiphestTaskEditController' => 'applications/maniphest/controller/taskedit',
'ManiphestTaskListController' => 'applications/maniphest/controller/tasklist',
'ManiphestTaskListView' => 'applications/maniphest/view/tasklist',
'ManiphestTaskPriority' => 'applications/maniphest/constants/priority',
'ManiphestTaskSelectorSearchController' => 'applications/maniphest/controller/taskselectorsearch',
'ManiphestTaskStatus' => 'applications/maniphest/constants/status',
'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',
'ManiphestTransactionSaveController' => 'applications/maniphest/controller/transactionsave',
'ManiphestTransactionType' => 'applications/maniphest/constants/transactiontype',
'Phabricator404Controller' => 'applications/base/controller/404',
'PhabricatorAuthController' => 'applications/auth/controller/base',
'PhabricatorConduitAPIController' => 'applications/conduit/controller/api',
'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',
'PhabricatorController' => 'applications/base/controller/base',
'PhabricatorDaemon' => 'infrastructure/daemon/base',
'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/console',
'PhabricatorDaemonController' => 'applications/daemon/controller/base',
+ 'PhabricatorDaemonTimelineConsoleController' => 'applications/daemon/controller/timeline',
+ 'PhabricatorDaemonTimelineEventController' => 'applications/daemon/controller/timelineevent',
'PhabricatorDirectoryCategory' => 'applications/directory/storage/category',
'PhabricatorDirectoryCategoryDeleteController' => 'applications/directory/controller/categorydelete',
'PhabricatorDirectoryCategoryEditController' => 'applications/directory/controller/categoryedit',
'PhabricatorDirectoryCategoryListController' => 'applications/directory/controller/categorylist',
'PhabricatorDirectoryController' => 'applications/directory/controller/base',
'PhabricatorDirectoryDAO' => 'applications/directory/storage/base',
'PhabricatorDirectoryItem' => 'applications/directory/storage/item',
'PhabricatorDirectoryItemDeleteController' => 'applications/directory/controller/itemdelete',
'PhabricatorDirectoryItemEditController' => 'applications/directory/controller/itemedit',
'PhabricatorDirectoryItemListController' => 'applications/directory/controller/itemlist',
'PhabricatorDirectoryMainController' => 'applications/directory/controller/main',
'PhabricatorDraft' => 'applications/draft/storage/draft',
'PhabricatorDraftDAO' => 'applications/draft/storage/base',
'PhabricatorEmailLoginController' => 'applications/auth/controller/email',
'PhabricatorEmailTokenController' => 'applications/auth/controller/emailtoken',
'PhabricatorEnv' => 'infrastructure/env',
'PhabricatorFile' => 'applications/files/storage/file',
'PhabricatorFileController' => 'applications/files/controller/base',
'PhabricatorFileDAO' => 'applications/files/storage/base',
'PhabricatorFileListController' => 'applications/files/controller/list',
'PhabricatorFileStorageBlob' => 'applications/files/storage/storageblob',
'PhabricatorFileURI' => 'applications/files/uri',
'PhabricatorFileUploadController' => 'applications/files/controller/upload',
'PhabricatorFileViewController' => 'applications/files/controller/view',
'PhabricatorGoodForNothingWorker' => 'infrastructure/daemon/workers/worker/goodfornothing',
'PhabricatorHandleObjectSelectorDataView' => 'applications/phid/handle/view/selector',
'PhabricatorLiskDAO' => 'applications/base/storage/lisk',
'PhabricatorLoginController' => 'applications/auth/controller/login',
'PhabricatorLogoutController' => 'applications/auth/controller/logout',
'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/base',
'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/amazonses',
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/phpmailerlite',
'PhabricatorMetaMTAController' => 'applications/metamta/controller/base',
'PhabricatorMetaMTADAO' => 'applications/metamta/storage/base',
'PhabricatorMetaMTADaemon' => 'applications/metamta/daemon/mta',
'PhabricatorMetaMTAListController' => 'applications/metamta/controller/list',
'PhabricatorMetaMTAMail' => 'applications/metamta/storage/mail',
'PhabricatorMetaMTAMailingList' => 'applications/metamta/storage/mailinglist',
'PhabricatorMetaMTAMailingListEditController' => 'applications/metamta/controller/mailinglistedit',
'PhabricatorMetaMTAMailingListsController' => 'applications/metamta/controller/mailinglists',
'PhabricatorMetaMTASendController' => 'applications/metamta/controller/send',
'PhabricatorMetaMTAViewController' => 'applications/metamta/controller/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',
'PhabricatorOAuthRegistrationController' => 'applications/auth/controller/oauthregistration/base',
'PhabricatorOAuthUnlinkController' => 'applications/auth/controller/unlink',
'PhabricatorObjectHandle' => 'applications/phid/handle',
'PhabricatorObjectHandleData' => 'applications/phid/handle/data',
'PhabricatorObjectSelectorDialog' => 'view/control/objectselector',
'PhabricatorPHID' => 'applications/phid/storage/phid',
'PhabricatorPHIDAllocateController' => 'applications/phid/controller/allocate',
'PhabricatorPHIDConstants' => 'applications/phid/constants',
'PhabricatorPHIDController' => 'applications/phid/controller/base',
'PhabricatorPHIDDAO' => 'applications/phid/storage/base',
'PhabricatorPHIDListController' => 'applications/phid/controller/list',
'PhabricatorPHIDLookupController' => 'applications/phid/controller/lookup',
'PhabricatorPHIDType' => 'applications/phid/storage/type',
'PhabricatorPHIDTypeEditController' => 'applications/phid/controller/typeedit',
'PhabricatorPHIDTypeListController' => 'applications/phid/controller/typelist',
'PhabricatorPeopleController' => 'applications/people/controller/base',
'PhabricatorPeopleEditController' => 'applications/people/controller/edit',
'PhabricatorPeopleListController' => 'applications/people/controller/list',
'PhabricatorPeopleProfileController' => 'applications/people/controller/profile',
'PhabricatorPeopleProfileEditController' => 'applications/people/controller/profileedit',
'PhabricatorProject' => 'applications/project/storage/project',
'PhabricatorProjectAffiliation' => 'applications/project/storage/affiliation',
'PhabricatorProjectAffiliationEditController' => 'applications/project/controller/editaffiliation',
'PhabricatorProjectController' => 'applications/project/controller/base',
'PhabricatorProjectDAO' => 'applications/project/storage/base',
'PhabricatorProjectEditController' => 'applications/project/controller/edit',
'PhabricatorProjectListController' => 'applications/project/controller/list',
'PhabricatorProjectProfile' => 'applications/project/storage/profile',
'PhabricatorProjectProfileController' => 'applications/project/controller/profile',
'PhabricatorRemarkupRuleDifferential' => 'infrastructure/markup/remarkup/markuprule/differential',
'PhabricatorRemarkupRuleManiphest' => 'infrastructure/markup/remarkup/markuprule/maniphest',
'PhabricatorRepository' => 'applications/repository/storage/repository',
'PhabricatorRepositoryCommit' => 'applications/repository/storage/commit',
+ 'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/base',
+ 'PhabricatorRepositoryCommitData' => 'applications/repository/storage/commitdata',
'PhabricatorRepositoryCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/base',
- 'PhabricatorRepositoryCommitParserDaemon' => 'applications/repository/daemon/commitparser',
+ 'PhabricatorRepositoryCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/base',
+ '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',
'PhabricatorRepositoryEditController' => 'applications/repository/controller/edit',
+ 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/git',
'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/git',
+ 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/git',
'PhabricatorRepositoryGitHubNotification' => 'applications/repository/storage/githubnotification',
'PhabricatorRepositoryGitHubPostReceiveController' => 'applications/repository/controller/github-post-receive',
'PhabricatorRepositoryGitPullDaemon' => 'applications/repository/daemon/gitpull',
'PhabricatorRepositoryListController' => 'applications/repository/controller/list',
+ 'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/svn',
+ 'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/svn',
'PhabricatorRepositoryType' => 'applications/repository/constants/repositorytype',
'PhabricatorSearchAbstractDocument' => 'applications/search/index/abstractdocument',
'PhabricatorSearchBaseController' => 'applications/search/controller/base',
'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',
'PhabricatorSearchExecutor' => 'applications/search/execute/base',
'PhabricatorSearchField' => 'applications/search/constants/field',
'PhabricatorSearchManiphestIndexer' => 'applications/search/index/indexer/maniphest',
'PhabricatorSearchMySQLExecutor' => 'applications/search/execute/mysql',
'PhabricatorSearchQuery' => 'applications/search/storage/query',
'PhabricatorSearchRelationship' => 'applications/search/constants/relationship',
'PhabricatorStandardPageView' => 'view/page/standard',
'PhabricatorTaskmasterDaemon' => 'infrastructure/daemon/workers/taskmaster',
'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',
'PhabricatorTypeaheadCommonDatasourceController' => 'applications/typeahead/controller/common',
'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/base',
'PhabricatorUser' => 'applications/people/storage/user',
'PhabricatorUserDAO' => 'applications/people/storage/base',
'PhabricatorUserOAuthInfo' => 'applications/people/storage/useroauthinfo',
'PhabricatorUserProfile' => 'applications/people/storage/profile',
'PhabricatorUserSettingsController' => 'applications/people/controller/settings',
'PhabricatorWorker' => 'infrastructure/daemon/workers/worker',
'PhabricatorWorkerDAO' => 'infrastructure/daemon/workers/storage/base',
'PhabricatorWorkerTask' => 'infrastructure/daemon/workers/storage/task',
'PhabricatorWorkerTaskData' => 'infrastructure/daemon/workers/storage/taskdata',
'PhabricatorXHProfController' => 'applications/xhprof/controller/base',
'PhabricatorXHProfProfileController' => 'applications/xhprof/controller/profile',
'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/symbol',
'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/toplevel',
),
'function' =>
array(
'_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_format_relative_time' => 'view/utils',
'phabricator_format_timestamp' => 'view/utils',
'phabricator_format_units_generic' => 'view/utils',
'phabricator_render_form' => 'infrastructure/javelin/markup',
'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(
'Aphront400Response' => 'AphrontResponse',
'Aphront404Response' => 'AphrontResponse',
'AphrontAjaxResponse' => 'AphrontResponse',
'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration',
'AphrontDefaultApplicationController' => 'AphrontController',
'AphrontDialogResponse' => 'AphrontResponse',
'AphrontDialogView' => 'AphrontView',
'AphrontErrorView' => 'AphrontView',
'AphrontFileResponse' => 'AphrontResponse',
'AphrontFormCheckboxControl' => 'AphrontFormControl',
'AphrontFormControl' => 'AphrontView',
'AphrontFormDividerControl' => 'AphrontFormControl',
'AphrontFormFileControl' => 'AphrontFormControl',
'AphrontFormMarkupControl' => 'AphrontFormControl',
'AphrontFormPasswordControl' => 'AphrontFormControl',
'AphrontFormRecaptchaControl' => 'AphrontFormControl',
'AphrontFormSelectControl' => 'AphrontFormControl',
'AphrontFormStaticControl' => 'AphrontFormControl',
'AphrontFormSubmitControl' => 'AphrontFormControl',
'AphrontFormTextAreaControl' => 'AphrontFormControl',
'AphrontFormTextControl' => 'AphrontFormControl',
'AphrontFormTokenizerControl' => 'AphrontFormControl',
'AphrontFormView' => 'AphrontView',
'AphrontHeadsupActionListView' => 'AphrontView',
'AphrontHeadsupActionView' => 'AphrontView',
'AphrontMySQLDatabaseConnection' => 'AphrontDatabaseConnection',
'AphrontNullView' => 'AphrontView',
'AphrontPageView' => 'AphrontView',
'AphrontPanelView' => 'AphrontView',
'AphrontQueryConnectionException' => 'AphrontQueryException',
'AphrontQueryConnectionLostException' => 'AphrontQueryRecoverableException',
'AphrontQueryCountException' => 'AphrontQueryException',
'AphrontQueryDuplicateKeyException' => 'AphrontQueryException',
'AphrontQueryObjectMissingException' => 'AphrontQueryException',
'AphrontQueryParameterException' => 'AphrontQueryException',
'AphrontQueryRecoverableException' => 'AphrontQueryException',
'AphrontRedirectException' => 'AphrontException',
'AphrontRedirectResponse' => 'AphrontResponse',
'AphrontRequestFailureView' => 'AphrontView',
'AphrontSideNavView' => 'AphrontView',
'AphrontTableView' => 'AphrontView',
'AphrontWebpageResponse' => 'AphrontResponse',
'CelerityResourceController' => 'AphrontController',
'ConduitAPI_conduit_connect_Method' => 'ConduitAPIMethod',
'ConduitAPI_conduit_ping_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_creatediff_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_createrevision_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_find_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getcommitmessage_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getcommitpaths_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getdiff_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_markcommitted_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_parsecommitmessage_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_setdiffproperty_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_updaterevision_Method' => 'ConduitAPIMethod',
'ConduitAPI_file_upload_Method' => 'ConduitAPIMethod',
'ConduitAPI_user_find_Method' => 'ConduitAPIMethod',
'DarkConsoleConfigPlugin' => 'DarkConsolePlugin',
'DarkConsoleController' => 'PhabricatorController',
'DarkConsoleErrorLogPlugin' => 'DarkConsolePlugin',
'DarkConsoleRequestPlugin' => 'DarkConsolePlugin',
'DarkConsoleServicesPlugin' => 'DarkConsolePlugin',
'DarkConsoleXHProfPlugin' => 'DarkConsolePlugin',
'DifferentialAddCommentView' => 'AphrontView',
'DifferentialAttachController' => 'DifferentialController',
'DifferentialCCWelcomeMail' => 'DifferentialReviewRequestMail',
'DifferentialChangeset' => 'DifferentialDAO',
'DifferentialChangesetDetailView' => 'AphrontView',
'DifferentialChangesetListView' => 'AphrontView',
'DifferentialChangesetViewController' => 'DifferentialController',
'DifferentialComment' => 'DifferentialDAO',
'DifferentialCommentMail' => 'DifferentialMail',
'DifferentialCommentPreviewController' => 'DifferentialController',
'DifferentialCommentSaveController' => 'DifferentialController',
'DifferentialController' => 'PhabricatorController',
'DifferentialDAO' => 'PhabricatorLiskDAO',
'DifferentialDiff' => 'DifferentialDAO',
'DifferentialDiffContentMail' => 'DifferentialMail',
'DifferentialDiffCreateController' => 'DifferentialController',
'DifferentialDiffProperty' => 'DifferentialDAO',
'DifferentialDiffTableOfContentsView' => 'AphrontView',
'DifferentialDiffViewController' => 'DifferentialController',
'DifferentialHunk' => 'DifferentialDAO',
'DifferentialInlineComment' => 'DifferentialDAO',
'DifferentialInlineCommentEditController' => 'DifferentialController',
'DifferentialInlineCommentPreviewController' => 'DifferentialController',
'DifferentialInlineCommentView' => 'AphrontView',
'DifferentialNewDiffMail' => 'DifferentialReviewRequestMail',
'DifferentialReviewRequestMail' => 'DifferentialMail',
'DifferentialRevision' => 'DifferentialDAO',
'DifferentialRevisionCommentListView' => 'AphrontView',
'DifferentialRevisionCommentView' => 'AphrontView',
'DifferentialRevisionDetailView' => 'AphrontView',
'DifferentialRevisionEditController' => 'DifferentialController',
'DifferentialRevisionListController' => 'DifferentialController',
'DifferentialRevisionUpdateHistoryView' => 'AphrontView',
'DifferentialRevisionViewController' => 'DifferentialController',
'DifferentialSubscribeController' => 'DifferentialController',
'DiffusionBrowseController' => 'DiffusionController',
'DiffusionBrowseFileController' => 'DiffusionController',
'DiffusionBrowseTableView' => 'AphrontView',
+ 'DiffusionCommitChangeTableView' => 'AphrontView',
+ 'DiffusionCommitController' => 'DiffusionController',
'DiffusionController' => 'PhabricatorController',
'DiffusionGitBrowseQuery' => 'DiffusionBrowseQuery',
'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery',
'DiffusionGitHistoryQuery' => 'DiffusionHistoryQuery',
'DiffusionGitRequest' => 'DiffusionRequest',
'DiffusionHistoryController' => 'DiffusionController',
'DiffusionHistoryTableView' => 'AphrontView',
'DiffusionHomeController' => 'DiffusionController',
'ManiphestController' => 'PhabricatorController',
'ManiphestDAO' => 'PhabricatorLiskDAO',
'ManiphestTask' => 'ManiphestDAO',
'ManiphestTaskDetailController' => 'ManiphestController',
'ManiphestTaskEditController' => 'ManiphestController',
'ManiphestTaskListController' => 'ManiphestController',
'ManiphestTaskListView' => 'AphrontView',
'ManiphestTaskSelectorSearchController' => 'ManiphestController',
'ManiphestTaskSummaryView' => 'AphrontView',
'ManiphestTransaction' => 'ManiphestDAO',
'ManiphestTransactionDetailView' => 'AphrontView',
'ManiphestTransactionListView' => 'AphrontView',
'ManiphestTransactionSaveController' => 'ManiphestController',
'Phabricator404Controller' => 'PhabricatorController',
'PhabricatorAuthController' => 'PhabricatorController',
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO',
'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
'PhabricatorConduitController' => 'PhabricatorController',
'PhabricatorConduitDAO' => 'PhabricatorLiskDAO',
'PhabricatorConduitLogController' => 'PhabricatorConduitController',
'PhabricatorConduitMethodCallLog' => 'PhabricatorConduitDAO',
'PhabricatorController' => 'AphrontController',
'PhabricatorDaemon' => 'PhutilDaemon',
'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController',
'PhabricatorDaemonController' => 'PhabricatorController',
+ 'PhabricatorDaemonTimelineConsoleController' => 'PhabricatorDaemonController',
+ 'PhabricatorDaemonTimelineEventController' => 'PhabricatorDaemonController',
'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO',
'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryCategoryEditController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryCategoryListController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryController' => 'PhabricatorController',
'PhabricatorDirectoryDAO' => 'PhabricatorLiskDAO',
'PhabricatorDirectoryItem' => 'PhabricatorDirectoryDAO',
'PhabricatorDirectoryItemDeleteController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryItemEditController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryItemListController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryMainController' => 'PhabricatorDirectoryController',
'PhabricatorDraft' => 'PhabricatorDraftDAO',
'PhabricatorDraftDAO' => 'PhabricatorLiskDAO',
'PhabricatorEmailLoginController' => 'PhabricatorAuthController',
'PhabricatorEmailTokenController' => 'PhabricatorAuthController',
'PhabricatorFile' => 'PhabricatorFileDAO',
'PhabricatorFileController' => 'PhabricatorController',
'PhabricatorFileDAO' => 'PhabricatorLiskDAO',
'PhabricatorFileListController' => 'PhabricatorFileController',
'PhabricatorFileStorageBlob' => 'PhabricatorFileDAO',
'PhabricatorFileUploadController' => 'PhabricatorFileController',
'PhabricatorFileViewController' => 'PhabricatorFileController',
'PhabricatorGoodForNothingWorker' => 'PhabricatorWorker',
'PhabricatorLiskDAO' => 'LiskDAO',
'PhabricatorLoginController' => 'PhabricatorAuthController',
'PhabricatorLogoutController' => 'PhabricatorAuthController',
'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter',
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMetaMTAController' => 'PhabricatorController',
'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO',
'PhabricatorMetaMTAListController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAMailingList' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAMailingListEditController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAMailingListsController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTASendController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAViewController' => 'PhabricatorMetaMTAController',
'PhabricatorOAuthDefaultRegistrationController' => 'PhabricatorOAuthRegistrationController',
'PhabricatorOAuthDiagnosticsController' => 'PhabricatorAuthController',
'PhabricatorOAuthFailureView' => 'AphrontView',
'PhabricatorOAuthLoginController' => 'PhabricatorAuthController',
'PhabricatorOAuthProviderFacebook' => 'PhabricatorOAuthProvider',
'PhabricatorOAuthProviderGithub' => 'PhabricatorOAuthProvider',
'PhabricatorOAuthRegistrationController' => 'PhabricatorAuthController',
'PhabricatorOAuthUnlinkController' => 'PhabricatorAuthController',
'PhabricatorPHID' => 'PhabricatorPHIDDAO',
'PhabricatorPHIDAllocateController' => 'PhabricatorPHIDController',
'PhabricatorPHIDController' => 'PhabricatorController',
'PhabricatorPHIDDAO' => 'PhabricatorLiskDAO',
'PhabricatorPHIDListController' => 'PhabricatorPHIDController',
'PhabricatorPHIDLookupController' => 'PhabricatorPHIDController',
'PhabricatorPHIDType' => 'PhabricatorPHIDDAO',
'PhabricatorPHIDTypeEditController' => 'PhabricatorPHIDController',
'PhabricatorPHIDTypeListController' => 'PhabricatorPHIDController',
'PhabricatorPeopleController' => 'PhabricatorController',
'PhabricatorPeopleEditController' => 'PhabricatorPeopleController',
'PhabricatorPeopleListController' => 'PhabricatorPeopleController',
'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController',
'PhabricatorPeopleProfileEditController' => 'PhabricatorPeopleController',
'PhabricatorProject' => 'PhabricatorProjectDAO',
'PhabricatorProjectAffiliation' => 'PhabricatorProjectDAO',
'PhabricatorProjectAffiliationEditController' => 'PhabricatorProjectController',
'PhabricatorProjectController' => 'PhabricatorController',
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
'PhabricatorProjectEditController' => 'PhabricatorProjectController',
'PhabricatorProjectListController' => 'PhabricatorProjectController',
'PhabricatorProjectProfile' => 'PhabricatorProjectDAO',
'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
'PhabricatorRemarkupRuleDifferential' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleManiphest' => 'PhutilRemarkupRule',
'PhabricatorRepository' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryCommit' => 'PhabricatorRepositoryDAO',
+ 'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
+ 'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryCommitDiscoveryDaemon' => 'PhabricatorRepositoryDaemon',
- 'PhabricatorRepositoryCommitParserDaemon' => 'PhabricatorRepositoryDaemon',
+ 'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
+ 'PhabricatorRepositoryCommitParserWorker' => 'PhabricatorWorker',
+ 'PhabricatorRepositoryCommitTaskDaemon' => 'PhabricatorRepositoryDaemon',
'PhabricatorRepositoryController' => 'PhabricatorController',
'PhabricatorRepositoryCreateController' => 'PhabricatorController',
'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO',
'PhabricatorRepositoryDaemon' => 'PhabricatorDaemon',
'PhabricatorRepositoryEditController' => 'PhabricatorController',
+ 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
+ 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorRepositoryGitHubNotification' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryGitHubPostReceiveController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryGitPullDaemon' => 'PhabricatorRepositoryDaemon',
'PhabricatorRepositoryListController' => 'PhabricatorController',
+ 'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
+ 'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorSearchBaseController' => 'PhabricatorController',
'PhabricatorSearchController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchDAO' => 'PhabricatorLiskDAO',
'PhabricatorSearchDifferentialIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorSearchDocument' => 'PhabricatorSearchDAO',
'PhabricatorSearchDocumentField' => 'PhabricatorSearchDAO',
'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO',
'PhabricatorSearchManiphestIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorSearchMySQLExecutor' => 'PhabricatorSearchExecutor',
'PhabricatorSearchQuery' => 'PhabricatorSearchDAO',
'PhabricatorStandardPageView' => 'AphrontPageView',
'PhabricatorTaskmasterDaemon' => 'PhabricatorDaemon',
'PhabricatorTimelineCursor' => 'PhabricatorTimelineDAO',
'PhabricatorTimelineDAO' => 'PhabricatorLiskDAO',
'PhabricatorTimelineEvent' => 'PhabricatorTimelineDAO',
'PhabricatorTimelineEventData' => 'PhabricatorTimelineDAO',
'PhabricatorTypeaheadCommonDatasourceController' => 'PhabricatorTypeaheadDatasourceController',
'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController',
'PhabricatorUser' => 'PhabricatorUserDAO',
'PhabricatorUserDAO' => 'PhabricatorLiskDAO',
'PhabricatorUserOAuthInfo' => 'PhabricatorUserDAO',
'PhabricatorUserProfile' => 'PhabricatorUserDAO',
'PhabricatorUserSettingsController' => 'PhabricatorPeopleController',
'PhabricatorWorkerDAO' => 'PhabricatorLiskDAO',
'PhabricatorWorkerTask' => 'PhabricatorWorkerDAO',
'PhabricatorWorkerTaskData' => 'PhabricatorWorkerDAO',
'PhabricatorXHProfController' => 'PhabricatorController',
'PhabricatorXHProfProfileController' => 'PhabricatorXHProfController',
'PhabricatorXHProfProfileSymbolView' => 'AphrontView',
'PhabricatorXHProfProfileTopLevelView' => 'AphrontView',
),
'requires_interface' =>
array(
),
));
diff --git a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
index 43c13010e4..aa07c7cbe1 100644
--- a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
+++ b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
@@ -1,310 +1,314 @@
<?php
/*
* Copyright 2011 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(
'/' => array(
'$' => 'PhabricatorDirectoryMainController',
),
'/directory/' => array(
'item/$'
=> 'PhabricatorDirectoryItemListController',
'item/edit/(?:(?P<id>\d+)/)?$'
=> 'PhabricatorDirectoryItemEditController',
'item/delete/(?P<id>\d+)/'
=> 'PhabricatorDirectoryItemDeleteController',
'category/$'
=> 'PhabricatorDirectoryCategoryListController',
'category/edit/(?:(?P<id>\d+)/)?$'
=> 'PhabricatorDirectoryCategoryEditController',
'category/delete/(?P<id>\d+)/'
=> 'PhabricatorDirectoryCategoryDeleteController',
),
'/file/' => array(
'$' => 'PhabricatorFileListController',
'upload/$' => 'PhabricatorFileUploadController',
'(?P<view>info)/(?P<phid>[^/]+)/' => 'PhabricatorFileViewController',
'(?P<view>view)/(?P<phid>[^/]+)/' => 'PhabricatorFileViewController',
'(?P<view>download)/(?P<phid>[^/]+)/' => 'PhabricatorFileViewController',
),
'/phid/' => array(
'$' => 'PhabricatorPHIDLookupController',
'list/$' => 'PhabricatorPHIDListController',
'type/$' => 'PhabricatorPHIDTypeListController',
'type/edit/(?:(?P<id>\d+)/)?$' => 'PhabricatorPHIDTypeEditController',
'new/$' => 'PhabricatorPHIDAllocateController',
),
'/people/' => array(
'$' => 'PhabricatorPeopleListController',
'edit/(?:(?P<username>\w+)/)?$' => 'PhabricatorPeopleEditController',
),
'/p/(?P<username>\w+)/$' => 'PhabricatorPeopleProfileController',
'/profile/' => array(
'edit/$' => 'PhabricatorPeopleProfileEditController',
),
'/conduit/' => array(
'$' => 'PhabricatorConduitConsoleController',
'method/(?P<method>[^/]+)$' => 'PhabricatorConduitConsoleController',
'log/$' => 'PhabricatorConduitLogController',
),
'/api/(?P<method>[^/]+)$' => 'PhabricatorConduitAPIController',
'/D(?P<id>\d+)' => 'DifferentialRevisionViewController',
'/differential/' => array(
'$' => 'DifferentialRevisionListController',
'filter/(?P<filter>\w+)/$' => 'DifferentialRevisionListController',
'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',
),
),
'attach/(?P<id>\d+)/(?P<type>\w+)/$' => 'DifferentialAttachController',
'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',
),
'/login/' => array(
'$' => 'PhabricatorLoginController',
'email/$' => 'PhabricatorEmailLoginController',
'etoken/(?P<token>\w+)/$' => 'PhabricatorEmailTokenController',
),
'/logout/$' => 'PhabricatorLogoutController',
'/oauth/' => array(
'(?P<provider>github|facebook)/' => array(
'login/$' => 'PhabricatorOAuthLoginController',
'diagnose/$' => 'PhabricatorOAuthDiagnosticsController',
'unlink/$' => 'PhabricatorOAuthUnlinkController',
),
),
'/xhprof/' => array(
'profile/(?P<phid>[^/]+)/$' => 'PhabricatorXHProfProfileController',
),
'/~/' => 'DarkConsoleController',
'/settings/' => array(
'(?:page/(?P<page>[^/]+)/)?$' => 'PhabricatorUserSettingsController',
),
'/maniphest/' => array(
'$' => 'ManiphestTaskListController',
'view/(?P<view>\w+)/$' => 'ManiphestTaskListController',
'task/' => array(
'create/$' => 'ManiphestTaskEditController',
'edit/(?P<id>\d+)/$' => 'ManiphestTaskEditController',
),
'transaction/' => array(
'save/' => 'ManiphestTransactionSaveController',
),
'select/search/$' => 'ManiphestTaskSelectorSearchController',
),
'/T(?P<id>\d+)$' => 'ManiphestTaskDetailController',
'/github-post-receive/(?P<id>\d+)/(?P<token>[^/]+)/$'
=> 'PhabricatorRepositoryGitHubPostReceiveController',
'/repository/' => array(
'$' => 'PhabricatorRepositoryListController',
'create/$' => 'PhabricatorRepositoryCreateController',
'edit/(?P<id>\d+)/(?:(?P<view>\w+)?/)?$' =>
'PhabricatorRepositoryEditController',
'delete/(?P<id>\d+)/$' => 'PhabricatorRepositoryDeleteController',
),
'/search/' => array(
'$' => 'PhabricatorSearchController',
'(?P<id>\d+)/$' => 'PhabricatorSearchController',
),
'/project/' => array(
'$' => 'PhabricatorProjectListController',
'edit/(?:(?P<id>\d+)/)?$' => 'PhabricatorProjectEditController',
'view/(?P<id>\d+)/$' => 'PhabricatorProjectProfileController',
'affiliation/(?P<id>\d+)/$'
=> 'PhabricatorProjectAffiliationEditController',
),
+ '/r(?P<callsign>[A-Z]+)(?P<commit>[a-z0-9]+)$'
+ => 'DiffusionCommitController',
'/diffusion/' => array(
'$' => 'DiffusionHomeController',
'(?P<callsign>[A-Z]+)' => array(
'/history/'.
'(?P<path>.*?)'.
'(?:[;](?P<commit>[a-z0-9]+))?'.
'$'
=> 'DiffusionHistoryController',
'/browse/'.
'(?P<path>.*?)'.
'(?:[;](?P<commit>[a-z0-9]+))?'.
'(?:[$](?P<line>\d+))?'.
'$'
=> 'DiffusionBrowseController',
),
),
'/daemon/' => array(
+ 'timeline/$' => 'PhabricatorDaemonTimelineConsoleController',
+ 'timeline/(?P<id>\d+)/$' => 'PhabricatorDaemonTimelineEventController',
'$' => 'PhabricatorDaemonConsoleController',
),
);
}
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) {
$class = phutil_escape_html(get_class($ex));
$message = phutil_escape_html($ex->getMessage());
$content =
'<div class="aphront-unhandled-exception">'.
'<h1>Unhandled Exception "'.$class.'": '.$message.'</h1>'.
'<code>'.phutil_escape_html((string)$ex).'</code>'.
'</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('Exception!')
->setClass('aphront-exception-dialog')
->setUser($user)
->appendChild($content)
->addCancelButton('/');
$response = new AphrontDialogResponse();
$response->setDialog($dialog);
return $response;
}
public function willSendResponse(AphrontResponse $response) {
$request = $this->getRequest();
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(),
));
}
} else if ($response instanceof Aphront404Response) {
$failure = new AphrontRequestFailureView();
$failure->setHeader('404 Not Found');
$failure->appendChild(
'<p>The page you requested was not found.</p>');
$view = new PhabricatorStandardPageView();
$view->setTitle('404 Not Found');
$view->setRequest($this->getRequest());
$view->appendChild($failure);
$response = new AphrontWebpageResponse();
$response->setContent($view->render());
$response->setHTTPResponseCode(404);
return $response;
}
return $response;
}
public function build404Controller() {
return array(new Phabricator404Controller($this->getRequest()), array());
}
}
diff --git a/src/applications/daemon/controller/base/PhabricatorDaemonController.php b/src/applications/daemon/controller/base/PhabricatorDaemonController.php
index 9892426fd0..c0ab524416 100644
--- a/src/applications/daemon/controller/base/PhabricatorDaemonController.php
+++ b/src/applications/daemon/controller/base/PhabricatorDaemonController.php
@@ -1,42 +1,46 @@
<?php
/*
* Copyright 2011 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 PhabricatorDaemonController extends PhabricatorController {
public function buildStandardPageResponse($view, array $data) {
$page = $this->buildStandardPageView();
$page->setApplicationName('Daemon Console');
- $page->setBaseURI('/');
+ $page->setBaseURI('/daemon/');
$page->setTitle(idx($data, 'title'));
$page->setTabs(
array(
'console' => array(
'href' => '/daemon/',
'name' => 'Console',
),
+ 'timeline' => array(
+ 'href' => '/daemon/timeline/',
+ 'name' => 'Timeline',
+ ),
),
idx($data, 'tab'));
$page->setGlyph("\xE2\x98\xAF");
$page->appendChild($view);
$response = new AphrontWebpageResponse();
return $response->setContent($page->render());
}
}
diff --git a/src/applications/daemon/controller/console/PhabricatorDaemonConsoleController.php b/src/applications/daemon/controller/console/PhabricatorDaemonConsoleController.php
index 9e40ae17b2..2a3a797ac7 100644
--- a/src/applications/daemon/controller/console/PhabricatorDaemonConsoleController.php
+++ b/src/applications/daemon/controller/console/PhabricatorDaemonConsoleController.php
@@ -1,70 +1,131 @@
<?php
/*
* Copyright 2011 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.
*/
class PhabricatorDaemonConsoleController extends PhabricatorDaemonController {
public function processRequest() {
- $request = $this->getRequest();
-
- if ($request->getStr('new')) {
- $task = new PhabricatorWorkerTask();
- $task->setTaskClass('PhabricatorGoodForNothingWorker');
- $task->setPriority(4);
- $task->setFailureCount(0);
- $task->save();
- }
-
- $tasks = id(new PhabricatorWorkerTask())
- ->loadAll();
+ $tasks = id(new PhabricatorWorkerTask())->loadAllWhere(
+ 'leaseOwner IS NOT NULL');
$rows = array();
foreach ($tasks as $task) {
$rows[] = array(
$task->getID(),
$task->getTaskClass(),
$task->getLeaseOwner(),
- $task->getLeaseExpires(),
- $task->getPriority(),
+ $task->getLeaseExpires() - time(),
$task->getFailureCount(),
);
}
- $table = new AphrontTableView($rows);
- $table->setHeaders(
+ $leased_table = new AphrontTableView($rows);
+ $leased_table->setHeaders(
array(
'ID',
'Class',
'Owner',
'Expries',
- 'Priority',
+ 'Failures',
+ ));
+ $leased_table->setColumnClasses(
+ array(
+ 'n',
+ 'wide',
+ '',
+ '',
+ 'n',
+ ));
+ $leased_table->setNoDataString('No tasks are leased by workers.');
+
+ $leased_panel = new AphrontPanelView();
+ $leased_panel->setHeader('Leased Tasks');
+ $leased_panel->appendChild($leased_table);
+
+ $task_table = new PhabricatorWorkerTask();
+ $queued = queryfx_all(
+ $task_table->establishConnection('r'),
+ 'SELECT taskClass, count(*) N FROM %T GROUP BY taskClass
+ ORDER BY N DESC',
+ $task_table->getTableName());
+
+ $rows = array();
+ foreach ($queued as $row) {
+ $rows[] = array(
+ phutil_escape_html($row['taskClass']),
+ number_format($row['N']),
+ );
+ }
+
+ $queued_table = new AphrontTableView($rows);
+ $queued_table->setHeaders(
+ array(
+ 'Class',
'Count',
));
+ $queued_table->setColumnClasses(
+ array(
+ 'wide',
+ 'n',
+ ));
+ $queued_table->setNoDataString('Task queue is empty.');
+
+ $queued_panel = new AphrontPanelView();
+ $queued_panel->setHeader('Queued Tasks');
+ $queued_panel->appendChild($queued_table);
+
+ $cursors = id(new PhabricatorTimelineCursor())
+ ->loadAll();
+
+ $rows = array();
+ foreach ($cursors as $cursor) {
+ $rows[] = array(
+ phutil_escape_html($cursor->getName()),
+ number_format($cursor->getPosition()),
+ );
+ }
+
+ $cursor_table = new AphrontTableView($rows);
+ $cursor_table->setHeaders(
+ array(
+ 'Name',
+ 'Position',
+ ));
+ $cursor_table->setColumnClasses(
+ array(
+ 'wide',
+ 'n',
+ ));
+ $cursor_table->setNoDataString('No timeline cursors exist.');
- $panel = new AphrontPanelView();
- $panel->setHeader('Tasks');
- $panel->appendChild($table);
+ $cursor_panel = new AphrontPanelView();
+ $cursor_panel->setHeader('Timeline Cursors');
+ $cursor_panel->appendChild($cursor_table);
return $this->buildStandardPageResponse(
- $panel,
+ array(
+ $leased_panel,
+ $queued_panel,
+ $cursor_panel,
+ ),
array(
'title' => 'Console',
'tab' => 'console',
));
}
}
diff --git a/src/applications/daemon/controller/console/__init__.php b/src/applications/daemon/controller/console/__init__.php
index 28cdb0bf7a..c07c4dd43a 100644
--- a/src/applications/daemon/controller/console/__init__.php
+++ b/src/applications/daemon/controller/console/__init__.php
@@ -1,17 +1,20 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/daemon/controller/base');
+phutil_require_module('phabricator', 'infrastructure/daemon/timeline/storage/cursor');
phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/task');
+phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phabricator', 'view/layout/panel');
+phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorDaemonConsoleController.php');
diff --git a/src/applications/daemon/controller/timeline/PhabricatorDaemonTimelineConsoleController.php b/src/applications/daemon/controller/timeline/PhabricatorDaemonTimelineConsoleController.php
new file mode 100644
index 0000000000..36fed14a97
--- /dev/null
+++ b/src/applications/daemon/controller/timeline/PhabricatorDaemonTimelineConsoleController.php
@@ -0,0 +1,70 @@
+<?php
+
+/*
+ * Copyright 2011 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.
+ */
+
+class PhabricatorDaemonTimelineConsoleController
+ extends PhabricatorDaemonController {
+
+ public function processRequest() {
+
+ $timeline_table = new PhabricatorTimelineEvent('NULL');
+
+ $events = queryfx_all(
+ $timeline_table->establishConnection('r'),
+ 'SELECT id, type FROM %T ORDER BY id DESC LIMIT 100',
+ $timeline_table->getTableName());
+
+ $rows = array();
+ foreach ($events as $event) {
+ $rows[] = array(
+ phutil_render_tag(
+ 'a',
+ array(
+ 'href' => '/daemon/timeline/'.$event['id'].'/',
+ ),
+ $event['id']),
+ phutil_escape_html($event['type']),
+ );
+ }
+
+ $event_table = new AphrontTableView($rows);
+ $event_table->setHeaders(
+ array(
+ 'ID',
+ 'Type',
+ ));
+ $event_table->setColumnClasses(
+ array(
+ null,
+ 'wide',
+ ));
+
+ $event_panel = new AphrontPanelView();
+ $event_panel->setHeader('Timeline Events');
+ $event_panel->appendChild($event_table);
+
+ return $this->buildStandardPageResponse(
+ array(
+ $event_panel,
+ ),
+ array(
+ 'title' => 'Timeline',
+ 'tab' => 'timeline',
+ ));
+ }
+
+}
diff --git a/src/applications/daemon/controller/console/__init__.php b/src/applications/daemon/controller/timeline/__init__.php
similarity index 53%
copy from src/applications/daemon/controller/console/__init__.php
copy to src/applications/daemon/controller/timeline/__init__.php
index 28cdb0bf7a..933eef2d80 100644
--- a/src/applications/daemon/controller/console/__init__.php
+++ b/src/applications/daemon/controller/timeline/__init__.php
@@ -1,17 +1,18 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/daemon/controller/base');
-phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/task');
+phutil_require_module('phabricator', 'infrastructure/daemon/timeline/storage/event');
+phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phabricator', 'view/layout/panel');
-phutil_require_module('phutil', 'utils');
+phutil_require_module('phutil', 'markup');
-phutil_require_source('PhabricatorDaemonConsoleController.php');
+phutil_require_source('PhabricatorDaemonTimelineConsoleController.php');
diff --git a/src/applications/daemon/controller/timelineevent/PhabricatorDaemonTimelineEventController.php b/src/applications/daemon/controller/timelineevent/PhabricatorDaemonTimelineEventController.php
new file mode 100644
index 0000000000..126d37a1b4
--- /dev/null
+++ b/src/applications/daemon/controller/timelineevent/PhabricatorDaemonTimelineEventController.php
@@ -0,0 +1,79 @@
+<?php
+
+/*
+ * Copyright 2011 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.
+ */
+
+class PhabricatorDaemonTimelineEventController
+ extends PhabricatorDaemonController {
+
+ private $id;
+
+ public function willProcessRequest(array $data) {
+ $this->id = $data['id'];
+ }
+
+ public function processRequest() {
+ $event = id(new PhabricatorTimelineEvent('NULL'))->load($this->id);
+ if (!$event) {
+ return new Aphront404Response();
+ }
+
+ $request = $this->getRequest();
+ $user = $request->getUser();
+
+ $data = id(new PhabricatorTimelineEventData())->loadOneWhere(
+ 'eventID = %d',
+ $event->getID());
+
+ if ($data) {
+ $data = json_encode($data->getEventData());
+ } else {
+ $data = 'null';
+ }
+
+ $form = new AphrontFormView();
+ $form
+ ->setUser($user)
+ ->appendChild(
+ id(new AphrontFormStaticControl())
+ ->setLabel('ID')
+ ->setValue($event->getID()))
+ ->appendChild(
+ id(new AphrontFormStaticControl())
+ ->setLabel('Type')
+ ->setValue($event->getType()))
+ ->appendChild(
+ id(new AphrontFormTextAreaControl())
+ ->setDisabled(true)
+ ->setLabel('Data')
+ ->setValue($data))
+ ->appendChild(
+ id(new AphrontFormSubmitControl())
+ ->addCancelButton('/daemon/timeline/'));
+
+ $panel = new AphrontPanelView();
+ $panel->setHeader('Event');
+ $panel->setWidth(AphrontPanelView::WIDTH_FORM);
+ $panel->appendChild($form);
+
+ return $this->buildStandardPageResponse(
+ $panel,
+ array(
+ 'title' => 'Timeline Event',
+ ));
+ }
+
+}
diff --git a/src/applications/daemon/controller/timelineevent/__init__.php b/src/applications/daemon/controller/timelineevent/__init__.php
new file mode 100644
index 0000000000..5423d87959
--- /dev/null
+++ b/src/applications/daemon/controller/timelineevent/__init__.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'aphront/response/404');
+phutil_require_module('phabricator', 'applications/daemon/controller/base');
+phutil_require_module('phabricator', 'infrastructure/daemon/timeline/storage/event');
+phutil_require_module('phabricator', 'infrastructure/daemon/timeline/storage/eventdata');
+phutil_require_module('phabricator', 'view/form/base');
+phutil_require_module('phabricator', 'view/form/control/submit');
+phutil_require_module('phabricator', 'view/layout/panel');
+
+phutil_require_module('phutil', 'utils');
+
+
+phutil_require_source('PhabricatorDaemonTimelineEventController.php');
diff --git a/src/applications/diffusion/controller/commit/DiffusionCommitController.php b/src/applications/diffusion/controller/commit/DiffusionCommitController.php
new file mode 100644
index 0000000000..8151f861b8
--- /dev/null
+++ b/src/applications/diffusion/controller/commit/DiffusionCommitController.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * Copyright 2011 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.
+ */
+
+class DiffusionCommitController extends DiffusionController {
+
+ public function processRequest() {
+ $drequest = $this->diffusionRequest;
+
+
+
+
+ $detail_panel = new AphrontPanelView();
+ $detail_panel->setHeader('Revision Detail');
+ $detail_panel->appendChild('<div>'.$drequest->getCommit().'</div>');
+
+ $change_table = new DiffusionCommitChangeTableView();
+ $change_table->setDiffusionRequest($drequest);
+ $change_table->setPathChanges(array());
+
+ $change_panel = new AphrontPanelView();
+ $change_panel->setHeader('Changes');
+ $change_panel->appendChild($change_table);
+
+ $change_list =
+ '<div style="margin: 2em; color: #666; padding: 1em; background: #eee;">'.
+ '(list of changes goes here)'.
+ '</div>';
+
+ return $this->buildStandardPageResponse(
+ array(
+ $detail_panel,
+ $change_panel,
+ $change_list,
+ ),
+ array(
+ 'title' => 'Diffusion',
+ ));
+ }
+
+}
diff --git a/src/applications/diffusion/controller/commit/__init__.php b/src/applications/diffusion/controller/commit/__init__.php
new file mode 100644
index 0000000000..8d10609002
--- /dev/null
+++ b/src/applications/diffusion/controller/commit/__init__.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'applications/diffusion/controller/base');
+phutil_require_module('phabricator', 'applications/diffusion/view/commitchangetable');
+phutil_require_module('phabricator', 'view/layout/panel');
+
+
+phutil_require_source('DiffusionCommitController.php');
diff --git a/src/applications/diffusion/view/commitchangetable/DiffusionCommitChangeTableView.php b/src/applications/diffusion/view/commitchangetable/DiffusionCommitChangeTableView.php
new file mode 100644
index 0000000000..566cb4c5f5
--- /dev/null
+++ b/src/applications/diffusion/view/commitchangetable/DiffusionCommitChangeTableView.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * Copyright 2011 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 DiffusionCommitChangeTableView extends AphrontView {
+
+ private $request;
+ private $pathChanges;
+
+ public function setDiffusionRequest(DiffusionRequest $request) {
+ $this->request = $request;
+ return $this;
+ }
+
+ public function setPathChanges(array $path_changes) {
+ $this->pathChanges = $path_changes;
+ return $this;
+ }
+
+ public function render() {
+ $rows = array();
+ foreach ($this->pathChanges as $change) {
+ $rows[] = array(
+ 'browse',
+ 'whatever',
+ $change->getPath(), // TODO: link
+ // TODO: etc etc
+ );
+ }
+
+ $view = new AphrontTableView($rows);
+ $view->setHeaders(
+ array(
+ 'History',
+ 'Change',
+ 'Path',
+ ));
+ $view->setColumnClasses(
+ array(
+ '',
+ '',
+ 'wide',
+ ));
+ $view->setNoDataString('This change has not been fully parsed yet.');
+
+ return $view->render();
+ }
+
+}
diff --git a/src/applications/repository/daemon/commitdiscovery/base/PhabricatorRepositoryCommitDiscoveryDaemon.php b/src/applications/repository/daemon/commitdiscovery/base/PhabricatorRepositoryCommitDiscoveryDaemon.php
index 9defcdd53d..b3f42e094a 100644
--- a/src/applications/repository/daemon/commitdiscovery/base/PhabricatorRepositoryCommitDiscoveryDaemon.php
+++ b/src/applications/repository/daemon/commitdiscovery/base/PhabricatorRepositoryCommitDiscoveryDaemon.php
@@ -1,45 +1,96 @@
<?php
/*
* Copyright 2011 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 PhabricatorRepositoryCommitDiscoveryDaemon
extends PhabricatorRepositoryDaemon {
private $repository;
+ private $commitCache = array();
final protected function getRepository() {
return $this->repository;
}
final public function run() {
$this->repository = $this->loadRepository();
$sleep = 15;
while (true) {
$found = $this->discoverCommits();
if ($found) {
$sleep = 15;
} else {
$sleep = min($sleep + 15, 60 * 15);
}
$this->sleep($sleep);
}
}
+ protected function isKnownCommit($target) {
+ if (isset($this->commitCache[$target])) {
+ return true;
+ }
+
+ $commit = id(new PhabricatorRepositoryCommit())->loadOneWhere(
+ 'repositoryPHID = %s AND commitIdentifier = %s',
+ $this->getRepository()->getPHID(),
+ $target);
+
+ if (!$commit) {
+ return false;
+ }
+
+ $this->commitCache[$target] = true;
+ while (count($this->commitCache) > 16) {
+ array_shift($this->commitCache);
+ }
+
+ return true;
+ }
+
+ protected function recordCommit($commit_identifier, $epoch) {
+ $repository = $this->getRepository();
+
+ $commit = new PhabricatorRepositoryCommit();
+ $commit->setRepositoryPHID($repository->getPHID());
+ $commit->setCommitIdentifier($commit_identifier);
+ $commit->setEpoch($epoch);
+
+ try {
+ $commit->save();
+ $event = new PhabricatorTimelineEvent(
+ 'cmit',
+ array(
+ 'id' => $commit->getID(),
+ ));
+ $event->recordEvent();
+
+ $this->commitCache[$commit_identifier] = true;
+ } catch (AphrontQueryDuplicateKeyException $ex) {
+ // Ignore. This can happen because we discover the same new commit
+ // more than once when looking at history, or because of races or
+ // data inconsistency or cosmic radiation; in any case, we're still
+ // in a good state if we ignore the failure.
+ }
+
+ $this->stillWorking();
+ }
+
abstract protected function discoverCommits();
}
diff --git a/src/applications/repository/daemon/commitdiscovery/base/__init__.php b/src/applications/repository/daemon/commitdiscovery/base/__init__.php
index b48312c05a..cde21de298 100644
--- a/src/applications/repository/daemon/commitdiscovery/base/__init__.php
+++ b/src/applications/repository/daemon/commitdiscovery/base/__init__.php
@@ -1,12 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/repository/daemon/base');
+phutil_require_module('phabricator', 'applications/repository/storage/commit');
+phutil_require_module('phabricator', 'infrastructure/daemon/timeline/storage/event');
+
+phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorRepositoryCommitDiscoveryDaemon.php');
diff --git a/src/applications/repository/daemon/commitdiscovery/git/PhabricatorRepositoryGitCommitDiscoveryDaemon.php b/src/applications/repository/daemon/commitdiscovery/git/PhabricatorRepositoryGitCommitDiscoveryDaemon.php
index 2c9e077b0c..9d8e9e746e 100644
--- a/src/applications/repository/daemon/commitdiscovery/git/PhabricatorRepositoryGitCommitDiscoveryDaemon.php
+++ b/src/applications/repository/daemon/commitdiscovery/git/PhabricatorRepositoryGitCommitDiscoveryDaemon.php
@@ -1,139 +1,95 @@
<?php
/*
* Copyright 2011 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.
*/
class PhabricatorRepositoryGitCommitDiscoveryDaemon
extends PhabricatorRepositoryCommitDiscoveryDaemon {
- private $lastCommit;
- private $commitCache = array();
-
protected function discoverCommits() {
// NOTE: PhabricatorRepositoryGitPullDaemon does the actual pulls, this
// just parses HEAD.
$repository = $this->getRepository();
- // TODO: this should be a constant somewhere
- if ($repository->getVersionControlSystem() != 'git') {
+ $vcs = $repository->getVersionControlSystem();
+ if ($vcs != PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) {
throw new Exception("Repository is not a git repository.");
}
$repository_phid = $repository->getPHID();
$repo_base = $repository->getDetail('local-path');
list($commit) = execx(
'(cd %s && git log -n1 --pretty="%%H")',
$repo_base);
$commit = trim($commit);
- if ($commit === $this->lastCommit ||
- $this->isKnownCommit($commit)) {
+ if ($this->isKnownCommit($commit)) {
return false;
}
- $this->lastCommit = $commit;
$this->discoverCommit($commit);
return true;
}
private function discoverCommit($commit) {
$discover = array();
$insert = array();
$repository = $this->getRepository();
$repo_base = $repository->getDetail('local-path');
$discover[] = $commit;
$insert[] = $commit;
while (true) {
$target = array_pop($discover);
list($parents) = execx(
'(cd %s && git log -n1 --pretty="%%P" %s)',
$repo_base,
$target);
$parents = array_filter(explode(' ', trim($parents)));
foreach ($parents as $parent) {
if (!$this->isKnownCommit($parent)) {
$discover[] = $parent;
$insert[] = $parent;
}
}
if (empty($discover)) {
break;
}
$this->stillWorking();
}
while (true) {
$target = array_pop($insert);
list($epoch) = execx(
'(cd %s && git log -n1 --pretty="%%at" %s)',
$repo_base,
$target);
$epoch = trim($epoch);
- $commit = new PhabricatorRepositoryCommit();
- $commit->setRepositoryPHID($this->getRepository()->getPHID());
- $commit->setCommitIdentifier($target);
- $commit->setEpoch($epoch);
- try {
- $commit->save();
- $event = new PhabricatorTimelineEvent(
- 'cmit',
- array(
- 'id' => $commit->getID(),
- ));
- $event->recordEvent();
- } catch (AphrontQueryDuplicateKeyException $ex) {
- // Ignore. This can happen because we discover the same new commit
- // more than once when looking at history, or because of races or
- // data inconsistency or cosmic radiation; in any case, we're still
- // in a good state if we ignore the failure.
- }
+ $this->recordCommit($target, $epoch);
+
if (empty($insert)) {
break;
}
- $this->stillWorking();
}
}
- private function isKnownCommit($target) {
- if (isset($this->commitCache[$target])) {
- return true;
- }
-
- $commit = id(new PhabricatorRepositoryCommit())->loadOneWhere(
- 'repositoryPHID = %s AND commitIdentifier = %s',
- $this->getRepository()->getPHID(),
- $target);
-
- if (!$commit) {
- return false;
- }
-
- $this->commitCache[$target] = true;
- if (count($this->commitCache) > 16) {
- array_shift($this->commitCache);
- }
-
- return true;
- }
-
}
diff --git a/src/applications/repository/daemon/commitdiscovery/git/__init__.php b/src/applications/repository/daemon/commitdiscovery/git/__init__.php
index 91b37d309a..4404f788e1 100644
--- a/src/applications/repository/daemon/commitdiscovery/git/__init__.php
+++ b/src/applications/repository/daemon/commitdiscovery/git/__init__.php
@@ -1,17 +1,15 @@
<?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/daemon/commitdiscovery/base');
-phutil_require_module('phabricator', 'applications/repository/storage/commit');
-phutil_require_module('phabricator', 'applications/timeline/storage/event');
phutil_require_module('phutil', 'future/exec');
-phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorRepositoryGitCommitDiscoveryDaemon.php');
diff --git a/src/applications/repository/daemon/commitdiscovery/svn/PhabricatorRepositorySvnCommitDiscoveryDaemon.php b/src/applications/repository/daemon/commitdiscovery/svn/PhabricatorRepositorySvnCommitDiscoveryDaemon.php
new file mode 100644
index 0000000000..44943d6fd3
--- /dev/null
+++ b/src/applications/repository/daemon/commitdiscovery/svn/PhabricatorRepositorySvnCommitDiscoveryDaemon.php
@@ -0,0 +1,77 @@
+<?php
+
+/*
+ * Copyright 2011 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.
+ */
+
+class PhabricatorRepositorySvnCommitDiscoveryDaemon
+ extends PhabricatorRepositoryCommitDiscoveryDaemon {
+
+ protected function discoverCommits() {
+ $repository = $this->getRepository();
+
+ $vcs = $repository->getVersionControlSystem();
+ if ($vcs != PhabricatorRepositoryType::REPOSITORY_TYPE_SVN) {
+ throw new Exception("Repository is not a svn repository.");
+ }
+
+ $repository_phid = $repository->getPHID();
+
+ $uri = $repository->getDetail('remote-uri');
+ list($xml) = execx(
+ 'svn log --xml --non-interactive --quiet --limit 1 %s@HEAD',
+ $uri);
+
+ // TODO: We need to slam the XML output into valid UTF-8.
+
+ $log = new SimpleXMLElement($xml);
+ $entry = $log->logentry[0];
+ $commit = (int)$entry['revision'];
+
+ if ($this->isKnownCommit($commit)) {
+ return false;
+ }
+
+ $this->discoverCommit($commit);
+
+ return true;
+ }
+
+ private function discoverCommit($commit) {
+ $discover = array();
+ $largest_known = $commit - 1;
+ while ($largest_known > 0 && !$this->isKnownCommit($largest_known)) {
+ $largest_known--;
+ }
+
+ $repository = $this->getRepository();
+ $uri = $repository->getDetail('remote-uri');
+
+ for ($ii = $largest_known + 1; $ii <= $commit; $ii++) {
+ list($xml) = execx(
+ 'svn log --xml --non-interactive --quiet --limit 1 %s@%d',
+ $uri,
+ $ii);
+ $log = new SimpleXMLElement($xml);
+ $entry = $log->logentry[0];
+
+ $identifier = (int)$entry['revision'];
+ $epoch = (int)strtotime((string)$entry->date[0]);
+
+ $this->recordCommit($identifier, $epoch);
+ }
+ }
+
+}
diff --git a/src/applications/repository/daemon/commitdiscovery/svn/__init__.php b/src/applications/repository/daemon/commitdiscovery/svn/__init__.php
new file mode 100644
index 0000000000..61d4b5a2af
--- /dev/null
+++ b/src/applications/repository/daemon/commitdiscovery/svn/__init__.php
@@ -0,0 +1,15 @@
+<?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/daemon/commitdiscovery/base');
+
+phutil_require_module('phutil', 'future/exec');
+
+
+phutil_require_source('PhabricatorRepositorySvnCommitDiscoveryDaemon.php');
diff --git a/src/applications/repository/daemon/commitparser/__init__.php b/src/applications/repository/daemon/commitparser/__init__.php
deleted file mode 100644
index 73440750a7..0000000000
--- a/src/applications/repository/daemon/commitparser/__init__.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-/**
- * This file is automatically generated. Lint this module to rebuild it.
- * @generated
- */
-
-
-
-phutil_require_module('phabricator', 'applications/repository/daemon/base');
-
-
-phutil_require_source('PhabricatorRepositoryCommitParserDaemon.php');
diff --git a/src/applications/repository/daemon/committask/PhabricatorRepositoryCommitTaskDaemon.php b/src/applications/repository/daemon/committask/PhabricatorRepositoryCommitTaskDaemon.php
new file mode 100644
index 0000000000..65874fed0f
--- /dev/null
+++ b/src/applications/repository/daemon/committask/PhabricatorRepositoryCommitTaskDaemon.php
@@ -0,0 +1,72 @@
+<?php
+
+/*
+ * Copyright 2011 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.
+ */
+
+class PhabricatorRepositoryCommitTaskDaemon
+ extends PhabricatorRepositoryDaemon {
+
+ final public function run() {
+ do {
+ $iterator = new PhabricatorTimelineIterator('cmittask', array('cmit'));
+ foreach ($iterator as $event) {
+ $data = $event->getData();
+
+ if (!$data) {
+ // TODO: This event can't be processed, provide some way to
+ // communicate that?
+ continue;
+ }
+
+ $commit = id(new PhabricatorRepositoryCommit())->load($data['id']);
+ if (!$commit) {
+ // TODO: Same as above.
+ continue;
+ }
+
+ // TODO: Cache these.
+ $repository = id(new PhabricatorRepository())->loadOneWhere(
+ 'phid = %s',
+ $commit->getRepositoryPHID());
+
+ $vcs = $repository->getVersionControlSystem();
+ switch ($vcs) {
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
+ $class = 'PhabricatorRepositoryGitCommitMessageParserWorker';
+ $task = new PhabricatorWorkerTask();
+ $task->setTaskClass($class);
+ $task->setData($commit->getID());
+ $task->save();
+ break;
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
+ $class = 'PhabricatorRepositorySvnCommitMessageParserWorker';
+ $task = new PhabricatorWorkerTask();
+ $task->setTaskClass($class);
+ $task->setData($commit->getID());
+ $task->save();
+ break;
+ default:
+ throw new Exception("Unknown repository type.");
+ }
+
+ $this->stillWorking();
+ }
+ sleep(1);
+ $this->stillWorking();
+ } while (true);
+ }
+
+}
diff --git a/src/applications/repository/daemon/committask/__init__.php b/src/applications/repository/daemon/committask/__init__.php
new file mode 100644
index 0000000000..3e85d352f5
--- /dev/null
+++ b/src/applications/repository/daemon/committask/__init__.php
@@ -0,0 +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/daemon/base');
+phutil_require_module('phabricator', 'applications/repository/storage/commit');
+phutil_require_module('phabricator', 'applications/repository/storage/repository');
+phutil_require_module('phabricator', 'infrastructure/daemon/timeline/cursor/iterator');
+phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/task');
+
+phutil_require_module('phutil', 'utils');
+
+
+phutil_require_source('PhabricatorRepositoryCommitTaskDaemon.php');
diff --git a/src/applications/repository/daemon/commitparser/PhabricatorRepositoryCommitParserDaemon.php b/src/applications/repository/storage/commitdata/PhabricatorRepositoryCommitData.php
similarity index 67%
rename from src/applications/repository/daemon/commitparser/PhabricatorRepositoryCommitParserDaemon.php
rename to src/applications/repository/storage/commitdata/PhabricatorRepositoryCommitData.php
index d2cf1c9765..1e4cf5e92b 100644
--- a/src/applications/repository/daemon/commitparser/PhabricatorRepositoryCommitParserDaemon.php
+++ b/src/applications/repository/storage/commitdata/PhabricatorRepositoryCommitData.php
@@ -1,22 +1,31 @@
<?php
/*
* Copyright 2011 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.
*/
-class PhabricatorRepositoryCommitParserDaemon
- extends PhabricatorRepositoryDaemon {
+class PhabricatorRepositoryCommitData extends PhabricatorRepositoryDAO {
+
+ protected $commitID;
+ protected $authorName;
+ protected $commitMessage;
+
+ public function getConfiguration() {
+ return array(
+ self::CONFIG_TIMESTAMPS => false,
+ ) + parent::getConfiguration();
+ }
}
diff --git a/src/applications/repository/storage/commitdata/__init__.php b/src/applications/repository/storage/commitdata/__init__.php
new file mode 100644
index 0000000000..57fe6d1dcf
--- /dev/null
+++ b/src/applications/repository/storage/commitdata/__init__.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'applications/repository/storage/base');
+
+
+phutil_require_source('PhabricatorRepositoryCommitData.php');
diff --git a/src/applications/repository/storage/repository/PhabricatorRepository.php b/src/applications/repository/storage/repository/PhabricatorRepository.php
index 0301ddf1ec..ad5041c2e1 100644
--- a/src/applications/repository/storage/repository/PhabricatorRepository.php
+++ b/src/applications/repository/storage/repository/PhabricatorRepository.php
@@ -1,51 +1,54 @@
<?php
/*
* Copyright 2011 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.
*/
class PhabricatorRepository extends PhabricatorRepositoryDAO {
+ const TABLE_PATH = 'repository_path';
+ const TABLE_PATHCHANGE = 'repository_pathchange';
+
protected $phid;
protected $name;
protected $callsign;
protected $versionControlSystem;
protected $details = array();
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'details' => self::SERIALIZATION_JSON,
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorPHIDConstants::PHID_TYPE_REPO);
}
public function getDetail($key, $default = null) {
return idx($this->details, $key, $default);
}
public function setDetail($key, $value) {
$this->details[$key] = $value;
return $this;
}
}
diff --git a/src/applications/repository/worker/base/PhabricatorRepositoryCommitParserWorker.php b/src/applications/repository/worker/base/PhabricatorRepositoryCommitParserWorker.php
new file mode 100644
index 0000000000..04043e5e77
--- /dev/null
+++ b/src/applications/repository/worker/base/PhabricatorRepositoryCommitParserWorker.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * Copyright 2011 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 PhabricatorRepositoryCommitParserWorker
+ extends PhabricatorWorker {
+
+ protected $commit;
+
+ final public function doWork() {
+ $commit_id = $this->getTaskData();
+ if (!$commit_id) {
+ return;
+ }
+
+ $commit = id(new PhabricatorRepositoryCommit())->load($commit_id);
+
+ if (!$commit) {
+ // TODO: Communicate permanent failure?
+ return;
+ }
+
+ $this->commit = $commit;
+
+ $repository = id(new PhabricatorRepository())->loadOneWhere(
+ 'phid = %s',
+ $commit->getRepositoryPHID());
+
+ if (!$repository) {
+ return;
+ }
+
+ return $this->parseCommit($repository, $commit);
+ }
+
+ abstract protected function parseCommit(
+ PhabricatorRepository $repository,
+ PhabricatorRepositoryCommit $commit);
+
+}
diff --git a/src/applications/repository/worker/base/__init__.php b/src/applications/repository/worker/base/__init__.php
new file mode 100644
index 0000000000..2b6b8ed4d5
--- /dev/null
+++ b/src/applications/repository/worker/base/__init__.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'applications/repository/storage/commit');
+phutil_require_module('phabricator', 'applications/repository/storage/repository');
+phutil_require_module('phabricator', 'infrastructure/daemon/workers/worker');
+
+phutil_require_module('phutil', 'utils');
+
+
+phutil_require_source('PhabricatorRepositoryCommitParserWorker.php');
diff --git a/src/applications/repository/worker/commitchangeparser/base/PhabricatorRepositoryCommitChangeParserWorker.php b/src/applications/repository/worker/commitchangeparser/base/PhabricatorRepositoryCommitChangeParserWorker.php
new file mode 100644
index 0000000000..68a7bc840e
--- /dev/null
+++ b/src/applications/repository/worker/commitchangeparser/base/PhabricatorRepositoryCommitChangeParserWorker.php
@@ -0,0 +1,69 @@
+<?php
+
+/*
+ * Copyright 2011 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 PhabricatorRepositoryCommitChangeParserWorker
+ extends PhabricatorRepositoryCommitParserWorker {
+
+ protected function lookupOrCreatePaths(array $paths) {
+ $repository = new PhabricatorRepository();
+ $conn_w = $repository->establishConnection('w');
+
+ $result_map = $this->lookupPaths($paths);
+
+ $missing_paths = array_fill_keys($paths, true);
+ $missing_paths = array_diff_key($missing_paths, $result_map);
+ $missing_paths = array_keys($missing_paths);
+
+ if ($missing_paths) {
+ foreach (array_chunk($missing_paths, 512) as $path_chunk) {
+ $sql = array();
+ foreach ($path_chunk as $path) {
+ $sql[] = qsprintf($conn_w, '(%s)', $path);
+ }
+ queryfx(
+ $conn_w,
+ 'INSERT INTO %T (path) VALUES %Q',
+ PhabricatorRepository::TABLE_PATH,
+ implode(', ', $sql));
+ }
+ $result_map += $this->lookupPaths($missing_paths);
+ }
+
+ return $result_map;
+ }
+
+ private function lookupPaths(array $paths) {
+ $repository = new PhabricatorRepository();
+ $conn_w = $repository->establishConnection('w');
+
+ $result_map = array();
+ foreach (array_chunk($paths, 512) as $path_chunk) {
+ $chunk_map = queryfx_all(
+ $conn_w,
+ 'SELECT path, id FROM %T WHERE path IN (%Ls)',
+ PhabricatorRepository::TABLE_PATH,
+ $path_chunk);
+ foreach ($chunk_map as $row) {
+ $result_map[$row['path']] = $row['id'];
+ }
+ }
+ return $result_map;
+ }
+
+
+}
diff --git a/src/applications/repository/worker/commitchangeparser/base/__init__.php b/src/applications/repository/worker/commitchangeparser/base/__init__.php
new file mode 100644
index 0000000000..08e8c51252
--- /dev/null
+++ b/src/applications/repository/worker/commitchangeparser/base/__init__.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'applications/repository/storage/repository');
+phutil_require_module('phabricator', 'applications/repository/worker/base');
+phutil_require_module('phabricator', 'storage/qsprintf');
+phutil_require_module('phabricator', 'storage/queryfx');
+
+
+phutil_require_source('PhabricatorRepositoryCommitChangeParserWorker.php');
diff --git a/src/applications/repository/worker/commitchangeparser/git/PhabricatorRepositoryGitCommitChangeParserWorker.php b/src/applications/repository/worker/commitchangeparser/git/PhabricatorRepositoryGitCommitChangeParserWorker.php
new file mode 100644
index 0000000000..5d80ac6ae5
--- /dev/null
+++ b/src/applications/repository/worker/commitchangeparser/git/PhabricatorRepositoryGitCommitChangeParserWorker.php
@@ -0,0 +1,215 @@
+<?php
+
+/*
+ * Copyright 2011 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.
+ */
+
+class PhabricatorRepositoryGitCommitChangeParserWorker
+ extends PhabricatorRepositoryCommitChangeParserWorker {
+
+ protected function parseCommit(
+ PhabricatorRepository $repository,
+ PhabricatorRepositoryCommit $commit) {
+
+ $local_path = $repository->getDetail('local-path');
+
+ list($raw) = execx(
+ '(cd %s && git log -n1 -M -C -B --find-copies-harder --raw -t '.
+ '--abbrev=40 --pretty=format: %s)',
+ $local_path,
+ $commit->getCommitIdentifier());
+
+ $changes = array();
+ $move_away = array();
+ $copy_away = array();
+ $lines = explode("\n", $raw);
+ foreach ($lines as $line) {
+ if (!strlen(trim($line))) {
+ continue;
+ }
+ list($old_mode, $new_mode,
+ $old_hash, $new_hash,
+ $more_stuff) = preg_split('/ +/', $line);
+
+ // We may only have two pieces here.
+ list($action, $src_path, $dst_path) = array_merge(
+ explode("\t", $more_stuff),
+ array(null));
+
+ $old_mode = intval($old_mode, 8);
+ $new_mode = intval($new_mode, 8);
+
+ $file_type = DifferentialChangeType::FILE_NORMAL;
+ if ($new_mode & 040000) {
+ $file_type = DifferentialChangeType::FILE_DIRECTORY;
+ } else if ($new_mode & 0120000) {
+ $file_type = DifferentialChangeType::FILE_SYMLINK;
+ }
+
+ // TODO: We can detect binary changes as git does, through a combination
+ // of running 'git check-attr' for stuff like 'binary', 'merge' or 'diff',
+ // and by falling back to inspecting the first 8,000 characters of the
+ // buffer for null bytes (this is seriously git's algorithm, see
+ // buffer_is_binary() in xdiff-interface.c).
+
+ $change_type = null;
+ $change_path = $src_path;
+ $change_target = null;
+
+ switch ($action[0]) {
+ case 'A':
+ $change_type = DifferentialChangeType::TYPE_ADD;
+ break;
+ case 'D':
+ $change_type = DifferentialChangeType::TYPE_DELETE;
+ break;
+ case 'C':
+ $change_type = DifferentialChangeType::TYPE_COPY_HERE;
+ $change_path = $dst_path;
+ $change_target = $src_path;
+ $copy_away[$change_target][] = $change_path;
+ break;
+ case 'R':
+ $change_type = DifferentialChangeType::TYPE_MOVE_HERE;
+ $change_path = $dst_path;
+ $change_target = $src_path;
+ $move_away[$change_target][] = $change_path;
+ break;
+ case 'M':
+ $change_type = DifferentialChangeType::TYPE_CHANGE;
+ break;
+ default:
+ throw new Exception("Failed to parse line '{$line}'.");
+ }
+
+ $changes[$change_path] = array(
+ 'repositoryID' => $repository->getID(),
+ 'commitID' => $commit->getID(),
+
+ 'path' => $change_path,
+ 'changeType' => $change_type,
+ 'fileType' => $file_type,
+ 'isDirect' => true,
+ 'commitSequence' => $commit->getEpoch(),
+
+ 'targetPath' => $change_target,
+ 'targetCommitID' => $change_target ? $commit->getID() : null,
+ );
+ }
+
+ foreach ($copy_away as $change_path => $destinations) {
+ if (isset($move_away[$change_path])) {
+ $change_type = DifferentialChangeType::TYPE_MULTICOPY;
+ $is_direct = true;
+ unset($move_away[$change_path]);
+ } else {
+ $change_type = DifferentialChangeType::TYPE_COPY_AWAY;
+ $is_direct = false;
+ }
+
+ $reference = $changes[reset($destinations)];
+
+ $changes[$change_path] = array(
+ 'repositoryID' => $repository->getID(),
+ 'commitID' => $commit->getID(),
+
+ 'path' => $change_path,
+ 'changeType' => $change_type,
+ 'fileType' => $reference['fileType'],
+ 'isDirect' => $is_direct,
+ 'commitSequence' => $commit->getEpoch(),
+
+ 'targetPath' => null,
+ 'targetCommitID' => null,
+ );
+ }
+
+ foreach ($move_away as $change_path => $destinations) {
+ $reference = $changes[reset($destinations)];
+
+ $changes[$change_path] = array(
+ 'repositoryID' => $repository->getID(),
+ 'commitID' => $commit->getID(),
+
+ 'path' => $change_path,
+ 'changeType' => DifferentialChangeType::TYPE_MOVE_AWAY,
+ 'fileType' => $reference['fileType'],
+ 'isDirect' => true,
+ 'commitSequence' => $commit->getEpoch(),
+
+ 'targetPath' => null,
+ 'targetCommitID' => null,
+ );
+ }
+
+ $paths = array();
+ foreach ($changes as $change) {
+ $paths[$change['path']] = true;
+ if ($change['targetPath']) {
+ $paths[$change['targetPath']] = true;
+ }
+ }
+
+ $path_map = $this->lookupOrCreatePaths(array_keys($paths));
+
+ foreach ($changes as $key => $change) {
+ $changes[$key]['pathID'] = $path_map[$change['path']];
+ if ($change['targetPath']) {
+ $changes[$key]['targetPathID'] = $path_map[$change['targetPath']];
+ } else {
+ $changes[$key]['targetPathID'] = null;
+ }
+ }
+
+ $conn_w = $repository->establishConnection('w');
+
+ $changes_sql = array();
+ foreach ($changes as $change) {
+ $values = array(
+ (int)$change['repositoryID'],
+ (int)$change['pathID'],
+ (int)$change['commitID'],
+ $change['targetPathID']
+ ? (int)$change['targetPathID']
+ : 'null',
+ $change['targetCommitID']
+ ? (int)$change['targetCommitID']
+ : 'null',
+ (int)$change['changeType'],
+ (int)$change['fileType'],
+ (int)$change['isDirect'],
+ (int)$change['commitSequence'],
+ );
+ $changes_sql[] = '('.implode(', ', $values).')';
+ }
+
+ queryfx(
+ $conn_w,
+ 'DELETE FROM %T WHERE commitID = %d',
+ PhabricatorRepository::TABLE_PATHCHANGE,
+ $commit->getID());
+ foreach (array_chunk($changes_sql, 256) as $sql_chunk) {
+ queryfx(
+ $conn_w,
+ 'INSERT INTO %T
+ (repositoryID, pathID, commitID, targetPathID, targetCommitID,
+ changeType, fileType, isDirect, commitSequence)
+ VALUES %Q',
+ PhabricatorRepository::TABLE_PATHCHANGE,
+ implode(', ', $sql_chunk));
+ }
+ }
+
+}
diff --git a/src/applications/repository/worker/commitchangeparser/git/__init__.php b/src/applications/repository/worker/commitchangeparser/git/__init__.php
new file mode 100644
index 0000000000..6bc6d8d55e
--- /dev/null
+++ b/src/applications/repository/worker/commitchangeparser/git/__init__.php
@@ -0,0 +1,17 @@
+<?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/storage/repository');
+phutil_require_module('phabricator', 'applications/repository/worker/commitchangeparser/base');
+phutil_require_module('phabricator', 'storage/queryfx');
+
+phutil_require_module('phutil', 'future/exec');
+
+
+phutil_require_source('PhabricatorRepositoryGitCommitChangeParserWorker.php');
diff --git a/src/infrastructure/daemon/timeline/storage/cursor/PhabricatorTimelineCursor.php b/src/applications/repository/worker/commitmessageparser/base/PhabricatorRepositoryCommitMessageParserWorker.php
similarity index 53%
copy from src/infrastructure/daemon/timeline/storage/cursor/PhabricatorTimelineCursor.php
copy to src/applications/repository/worker/commitmessageparser/base/PhabricatorRepositoryCommitMessageParserWorker.php
index 6a1d379d5f..c617125338 100644
--- a/src/infrastructure/daemon/timeline/storage/cursor/PhabricatorTimelineCursor.php
+++ b/src/applications/repository/worker/commitmessageparser/base/PhabricatorRepositoryCommitMessageParserWorker.php
@@ -1,31 +1,37 @@
<?php
/*
* Copyright 2011 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.
*/
-class PhabricatorTimelineCursor extends PhabricatorTimelineDAO {
+abstract class PhabricatorRepositoryCommitMessageParserWorker
+ extends PhabricatorRepositoryCommitParserWorker {
- protected $name;
- protected $position;
+ final protected function updateCommitData($author, $message) {
+ $commit = $this->commit;
- public function getConfiguration() {
- return array(
- self::CONFIG_IDS => self::IDS_MANUAL,
- self::CONFIG_TIMESTAMPS => false,
- ) + parent::getConfiguration();
+ $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere(
+ 'commitID = %d',
+ $commit->getID());
+ if (!$data) {
+ $data = new PhabricatorRepositoryCommitData();
+ }
+ $data->setCommitID($commit->getID());
+ $data->setAuthorName($author);
+ $data->setCommitMessage($message);
+ $data->save();
}
}
diff --git a/src/applications/repository/worker/commitmessageparser/base/__init__.php b/src/applications/repository/worker/commitmessageparser/base/__init__.php
new file mode 100644
index 0000000000..1add9e0528
--- /dev/null
+++ b/src/applications/repository/worker/commitmessageparser/base/__init__.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'applications/repository/storage/commitdata');
+phutil_require_module('phabricator', 'applications/repository/worker/base');
+
+phutil_require_module('phutil', 'utils');
+
+
+phutil_require_source('PhabricatorRepositoryCommitMessageParserWorker.php');
diff --git a/src/applications/repository/worker/commitmessageparser/git/PhabricatorRepositoryGitCommitMessageParserWorker.php b/src/applications/repository/worker/commitmessageparser/git/PhabricatorRepositoryGitCommitMessageParserWorker.php
new file mode 100644
index 0000000000..0ad674752b
--- /dev/null
+++ b/src/applications/repository/worker/commitmessageparser/git/PhabricatorRepositoryGitCommitMessageParserWorker.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * Copyright 2011 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.
+ */
+
+class PhabricatorRepositoryGitCommitMessageParserWorker
+ extends PhabricatorRepositoryCommitMessageParserWorker {
+
+ public function parseCommit(
+ PhabricatorRepository $repository,
+ PhabricatorRepositoryCommit $commit) {
+
+ $local_path = $repository->getDetail('local-path');
+
+ list($info) = execx(
+ '(cd %s && git log -n 1 --pretty=format:%%an%%x00%%B %s)',
+ $local_path,
+ $commit->getCommitIdentifier());
+
+ // TODO: Need to slam UTF8?
+
+ list($author, $message) = explode("\0", $info);
+
+ $this->updateCommitData($author, $message);
+
+ $task = new PhabricatorWorkerTask();
+ $task->setTaskClass('PhabricatorRepositoryGitCommitChangeParserWorker');
+ $task->setData($commit->getID());
+ $task->save();
+ }
+
+}
diff --git a/src/applications/repository/worker/commitmessageparser/git/__init__.php b/src/applications/repository/worker/commitmessageparser/git/__init__.php
new file mode 100644
index 0000000000..f139ac2819
--- /dev/null
+++ b/src/applications/repository/worker/commitmessageparser/git/__init__.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'applications/repository/worker/commitmessageparser/base');
+phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/task');
+
+phutil_require_module('phutil', 'future/exec');
+
+
+phutil_require_source('PhabricatorRepositoryGitCommitMessageParserWorker.php');
diff --git a/src/applications/repository/worker/commitmessageparser/svn/PhabricatorRepositorySvnCommitMessageParserWorker.php b/src/applications/repository/worker/commitmessageparser/svn/PhabricatorRepositorySvnCommitMessageParserWorker.php
new file mode 100644
index 0000000000..f31b09f5c0
--- /dev/null
+++ b/src/applications/repository/worker/commitmessageparser/svn/PhabricatorRepositorySvnCommitMessageParserWorker.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * Copyright 2011 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.
+ */
+
+class PhabricatorRepositorySvnCommitMessageParserWorker
+ extends PhabricatorRepositoryCommitMessageParserWorker {
+
+ public function parseCommit(
+ PhabricatorRepository $repository,
+ PhabricatorRepositoryCommit $commit) {
+
+ $uri = $repository->getDetail('remote-uri');
+
+ list($xml) = execx(
+ 'svn log --xml --limit 1 --non-interactive %s@%d',
+ $uri,
+ $commit->getCommitIdentifier());
+
+ // TODO: Need to slam UTF8.
+
+ $log = new SimpleXMLElement($xml);
+ $entry = $log->logentry[0];
+
+ $author = (string)$entry->author;
+ $message = (string)$entry->msg;
+
+ $this->updateCommitData($author, $message);
+ }
+
+}
diff --git a/src/applications/repository/worker/commitmessageparser/svn/__init__.php b/src/applications/repository/worker/commitmessageparser/svn/__init__.php
new file mode 100644
index 0000000000..e8bb732e78
--- /dev/null
+++ b/src/applications/repository/worker/commitmessageparser/svn/__init__.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'applications/repository/worker/commitmessageparser/base');
+
+phutil_require_module('phutil', 'future/exec');
+
+
+phutil_require_source('PhabricatorRepositorySvnCommitMessageParserWorker.php');
diff --git a/src/infrastructure/daemon/timeline/cursor/iterator/PhabricatorTimelineIterator.php b/src/infrastructure/daemon/timeline/cursor/iterator/PhabricatorTimelineIterator.php
index 1b13cf21d8..1aadedeefc 100644
--- a/src/infrastructure/daemon/timeline/cursor/iterator/PhabricatorTimelineIterator.php
+++ b/src/infrastructure/daemon/timeline/cursor/iterator/PhabricatorTimelineIterator.php
@@ -1,115 +1,116 @@
<?php
/*
* Copyright 2011 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.
*/
class PhabricatorTimelineIterator implements Iterator {
protected $cursorName;
protected $eventTypes;
protected $cursor;
protected $index = -1;
protected $events = array();
const LOAD_CHUNK_SIZE = 128;
public function __construct($cursor_name, array $event_types) {
$this->cursorName = $cursor_name;
$this->eventTypes = $event_types;
}
protected function loadEvents() {
if (!$this->cursor) {
$this->cursor = id(new PhabricatorTimelineCursor())->loadOneWhere(
'name = %s',
$this->cursorName);
if (!$this->cursor) {
$cursor = new PhabricatorTimelineCursor();
$cursor->setName($this->cursorName);
$cursor->setPosition(0);
$cursor->save();
$this->cursor = $cursor;
}
}
- $event = new PhabricatorTimelineEvent();
+ $event = new PhabricatorTimelineEvent('NULL');
$event_data = new PhabricatorTimelineEventData();
$raw_data = queryfx_all(
$event->establishConnection('r'),
'SELECT event.*, event_data.eventData eventData
- FROM %T event WHERE event.id > %d AND event.type in (%Ls)
+ FROM %T event
LEFT JOIN %T event_data ON event_data.eventID = event.id
+ WHERE event.id > %d AND event.type in (%Ls)
ORDER BY event.id ASC LIMIT %d',
$event->getTableName(),
+ $event_data->getTableName(),
$this->cursor->getPosition(),
$this->eventTypes,
- $event_data->getTableName(),
self::LOAD_CHUNK_SIZE);
$events = $event->loadAllFromArray($raw_data);
$events = mpull($events, null, 'getID');
$raw_data = ipull($raw_data, 'eventData', 'id');
foreach ($raw_data as $id => $data) {
if ($data) {
$decoded = json_decode($data, true);
$events[$id]->setData($decoded);
}
}
$this->events = $events;
if ($this->events) {
$this->events = array_values($this->events);
$this->index = 0;
} else {
$this->cursor = null;
}
}
public function current() {
return $this->events[$this->index];
}
public function key() {
return $this->events[$this->index]->getID();
}
public function next() {
if ($this->valid()) {
$this->cursor->setPosition($this->key());
$this->cursor->save();
}
$this->index++;
if (!$this->valid()) {
$this->loadEvents();
}
}
public function valid() {
return isset($this->events[$this->index]);
}
public function rewind() {
if (!$this->valid()) {
$this->loadEvents();
}
}
}
diff --git a/src/infrastructure/daemon/timeline/storage/cursor/PhabricatorTimelineCursor.php b/src/infrastructure/daemon/timeline/storage/cursor/PhabricatorTimelineCursor.php
index 6a1d379d5f..a55375c40b 100644
--- a/src/infrastructure/daemon/timeline/storage/cursor/PhabricatorTimelineCursor.php
+++ b/src/infrastructure/daemon/timeline/storage/cursor/PhabricatorTimelineCursor.php
@@ -1,31 +1,42 @@
<?php
/*
* Copyright 2011 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.
*/
class PhabricatorTimelineCursor extends PhabricatorTimelineDAO {
protected $name;
protected $position;
+ public function getIDKey() {
+ return 'name';
+ }
+
public function getConfiguration() {
return array(
self::CONFIG_IDS => self::IDS_MANUAL,
self::CONFIG_TIMESTAMPS => false,
) + parent::getConfiguration();
}
+ public function shouldInsertWhenSaved() {
+ if ($this->position == 0) {
+ return true;
+ }
+ return false;
+ }
+
}
diff --git a/src/infrastructure/daemon/workers/storage/task/PhabricatorWorkerTask.php b/src/infrastructure/daemon/workers/storage/task/PhabricatorWorkerTask.php
index f41b3ceba2..9d980095db 100644
--- a/src/infrastructure/daemon/workers/storage/task/PhabricatorWorkerTask.php
+++ b/src/infrastructure/daemon/workers/storage/task/PhabricatorWorkerTask.php
@@ -1,60 +1,82 @@
<?php
/*
* Copyright 2011 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.
*/
class PhabricatorWorkerTask extends PhabricatorWorkerDAO {
protected $taskClass;
protected $leaseOwner;
protected $leaseExpires;
- protected $priority;
protected $failureCount;
private $serverTime;
private $localTime;
+ private $data;
public function getConfiguration() {
return array(
self::CONFIG_TIMESTAMPS => false,
) + parent::getConfiguration();
}
public function setServerTime($server_time) {
$this->serverTime = $server_time;
$this->localTime = time();
return $this;
}
public function setLeaseDuration($lease_duration) {
$server_lease_expires = $this->serverTime + $lease_duration;
$this->setLeaseExpires($server_lease_expires);
return $this->save();
}
public function save() {
if ($this->leaseOwner) {
$current_server_time = $this->serverTime + (time() - $this->localTime);
if ($current_server_time >= $this->leaseExpires) {
throw new Exception("Trying to update task after lease expiration!");
}
}
- return parent::save();
+ $is_new = !$this->getID();
+ if ($is_new) {
+ $this->failureCount = 0;
+ }
+
+ $ret = parent::save();
+
+ if ($is_new && $this->data) {
+ $data = new PhabricatorWorkerTaskData();
+ $data->setTaskID($this->getID());
+ $data->setData($this->data);
+ $data->save();
+ }
+
+ return $ret;
}
+ public function setData($data) {
+ $this->data = $data;
+ return $this;
+ }
+
+ public function getData() {
+ return $this->data;
+ }
}
diff --git a/src/infrastructure/daemon/workers/storage/task/__init__.php b/src/infrastructure/daemon/workers/storage/task/__init__.php
index 933817be3c..0a7539275a 100644
--- a/src/infrastructure/daemon/workers/storage/task/__init__.php
+++ b/src/infrastructure/daemon/workers/storage/task/__init__.php
@@ -1,12 +1,13 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/base');
+phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/taskdata');
phutil_require_source('PhabricatorWorkerTask.php');
diff --git a/src/infrastructure/daemon/workers/taskmaster/PhabricatorTaskmasterDaemon.php b/src/infrastructure/daemon/workers/taskmaster/PhabricatorTaskmasterDaemon.php
index 27731b1f3d..4a5d202312 100644
--- a/src/infrastructure/daemon/workers/taskmaster/PhabricatorTaskmasterDaemon.php
+++ b/src/infrastructure/daemon/workers/taskmaster/PhabricatorTaskmasterDaemon.php
@@ -1,121 +1,128 @@
<?php
/*
* Copyright 2011 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.
*/
class PhabricatorTaskmasterDaemon extends PhabricatorDaemon {
public function run() {
$lease_ownership_name = $this->getLeaseOwnershipName();
$task_table = new PhabricatorWorkerTask();
$taskdata_table = new PhabricatorWorkerTaskData();
$sleep = 0;
do {
$conn_w = $task_table->establishConnection('w');
queryfx(
$conn_w,
'UPDATE %T SET leaseOwner = %s, leaseExpires = UNIX_TIMESTAMP() + 15
- WHERE leaseOwner IS NULL
- OR leaseExpires < UNIX_TIMESTAMP()
- ORDER BY leaseOwner IS NULL, failureCount, priority
- LIMIT 1',
+ WHERE leaseOwner IS NULL LIMIT 1',
$task_table->getTableName(),
$lease_ownership_name);
$rows = $conn_w->getAffectedRows();
+ if (!$rows) {
+ $rows = queryfx(
+ $conn_w,
+ 'UPDATE %T SET leaseOwner = %s, leaseExpires = UNIX_TIMESTAMP() + 15
+ WHERE leaseExpires < UNIX_TIMESTAMP() LIMIT 1',
+ $task_table->getTableName(),
+ $lease_ownership_name);
+ $rows = $conn_w->getAffectedRows();
+ }
+
if ($rows) {
$data = queryfx_all(
$conn_w,
'SELECT task.*, taskdata.data _taskData, UNIX_TIMESTAMP() _serverTime
FROM %T task LEFT JOIN %T taskdata
ON taskdata.taskID = task.id
WHERE leaseOwner = %s AND leaseExpires > UNIX_TIMESTAMP()
LIMIT 1',
$task_table->getTableName(),
$taskdata_table->getTableName(),
$lease_ownership_name);
$tasks = $task_table->loadAllFromArray($data);
$tasks = mpull($tasks, null, 'getID');
$task_data = array();
foreach ($data as $row) {
$tasks[$row['id']]->setServerTime($row['_serverTime']);
if ($row['_taskData']) {
$task_data[$row['id']] = json_decode($row['_taskData'], true);
} else {
$task_data[$row['id']] = null;
}
}
foreach ($tasks as $task) {
// TODO: We should detect if we acquired a task with an expired lease
// and log about it / bump up failure count.
// TODO: We should detect if we acquired a task with an excessive
// failure count and fail it permanently.
$data = idx($task_data, $task->getID());
$class = $task->getTaskClass();
try {
PhutilSymbolLoader::loadClass($class);
if (!is_subclass_of($class, 'PhabricatorWorker')) {
throw new Exception(
"Task class '{$class}' does not extend PhabricatorWorker.");
}
$worker = newv($class, array($data));
$lease = $worker->getRequiredLeaseTime();
if ($lease !== null) {
$task->setLeaseDuration($lease);
}
$worker->executeTask();
$task->delete();
if ($data !== null) {
queryfx(
$conn_w,
'DELETE FROM %T WHERE taskID = %d',
- $taskdata_table,
+ $taskdata_table->getTableName(),
$task->getID());
}
} catch (Exception $ex) {
$task->setFailureCount($task->getFailureCount() + 1);
$task->save();
throw $ex;
}
}
$sleep = 0;
} else {
$sleep = min($sleep + 1, 30);
}
$this->sleep($sleep);
} while (true);
}
private function getLeaseOwnershipName() {
static $name = null;
if ($name === null) {
$name = getmypid().':'.time().':'.php_uname('n');
}
return $name;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 10, 11:45 PM (7 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
141368
Default Alt Text
(130 KB)

Event Timeline