mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-29 10:12:41 +01:00
Increase parseriness of some parsery things.
Summary: None of these are parsnips. Test Plan: Reviewers: CC:
This commit is contained in:
parent
ec084ca419
commit
8bcbeface1
42 changed files with 1359 additions and 100 deletions
42
resources/sql/patches/006.repository.sql
Normal file
42
resources/sql/patches/006.repository.sql
Normal file
|
@ -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)
|
||||||
|
);
|
|
@ -146,6 +146,8 @@ phutil_register_library_map(array(
|
||||||
'DiffusionBrowseFileController' => 'applications/diffusion/controller/file',
|
'DiffusionBrowseFileController' => 'applications/diffusion/controller/file',
|
||||||
'DiffusionBrowseQuery' => 'applications/diffusion/query/browse/base',
|
'DiffusionBrowseQuery' => 'applications/diffusion/query/browse/base',
|
||||||
'DiffusionBrowseTableView' => 'applications/diffusion/view/browsetable',
|
'DiffusionBrowseTableView' => 'applications/diffusion/view/browsetable',
|
||||||
|
'DiffusionCommitChangeTableView' => 'applications/diffusion/view/commitchangetable',
|
||||||
|
'DiffusionCommitController' => 'applications/diffusion/controller/commit',
|
||||||
'DiffusionController' => 'applications/diffusion/controller/base',
|
'DiffusionController' => 'applications/diffusion/controller/base',
|
||||||
'DiffusionFileContent' => 'applications/diffusion/data/filecontent',
|
'DiffusionFileContent' => 'applications/diffusion/data/filecontent',
|
||||||
'DiffusionFileContentQuery' => 'applications/diffusion/query/filecontent/base',
|
'DiffusionFileContentQuery' => 'applications/diffusion/query/filecontent/base',
|
||||||
|
@ -192,6 +194,8 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorDaemon' => 'infrastructure/daemon/base',
|
'PhabricatorDaemon' => 'infrastructure/daemon/base',
|
||||||
'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/console',
|
'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/console',
|
||||||
'PhabricatorDaemonController' => 'applications/daemon/controller/base',
|
'PhabricatorDaemonController' => 'applications/daemon/controller/base',
|
||||||
|
'PhabricatorDaemonTimelineConsoleController' => 'applications/daemon/controller/timeline',
|
||||||
|
'PhabricatorDaemonTimelineEventController' => 'applications/daemon/controller/timelineevent',
|
||||||
'PhabricatorDirectoryCategory' => 'applications/directory/storage/category',
|
'PhabricatorDirectoryCategory' => 'applications/directory/storage/category',
|
||||||
'PhabricatorDirectoryCategoryDeleteController' => 'applications/directory/controller/categorydelete',
|
'PhabricatorDirectoryCategoryDeleteController' => 'applications/directory/controller/categorydelete',
|
||||||
'PhabricatorDirectoryCategoryEditController' => 'applications/directory/controller/categoryedit',
|
'PhabricatorDirectoryCategoryEditController' => 'applications/directory/controller/categoryedit',
|
||||||
|
@ -274,18 +278,26 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorRemarkupRuleManiphest' => 'infrastructure/markup/remarkup/markuprule/maniphest',
|
'PhabricatorRemarkupRuleManiphest' => 'infrastructure/markup/remarkup/markuprule/maniphest',
|
||||||
'PhabricatorRepository' => 'applications/repository/storage/repository',
|
'PhabricatorRepository' => 'applications/repository/storage/repository',
|
||||||
'PhabricatorRepositoryCommit' => 'applications/repository/storage/commit',
|
'PhabricatorRepositoryCommit' => 'applications/repository/storage/commit',
|
||||||
|
'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/base',
|
||||||
|
'PhabricatorRepositoryCommitData' => 'applications/repository/storage/commitdata',
|
||||||
'PhabricatorRepositoryCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/base',
|
'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',
|
'PhabricatorRepositoryController' => 'applications/repository/controller/base',
|
||||||
'PhabricatorRepositoryCreateController' => 'applications/repository/controller/create',
|
'PhabricatorRepositoryCreateController' => 'applications/repository/controller/create',
|
||||||
'PhabricatorRepositoryDAO' => 'applications/repository/storage/base',
|
'PhabricatorRepositoryDAO' => 'applications/repository/storage/base',
|
||||||
'PhabricatorRepositoryDaemon' => 'applications/repository/daemon/base',
|
'PhabricatorRepositoryDaemon' => 'applications/repository/daemon/base',
|
||||||
'PhabricatorRepositoryEditController' => 'applications/repository/controller/edit',
|
'PhabricatorRepositoryEditController' => 'applications/repository/controller/edit',
|
||||||
|
'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/git',
|
||||||
'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/git',
|
'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/git',
|
||||||
|
'PhabricatorRepositoryGitCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/git',
|
||||||
'PhabricatorRepositoryGitHubNotification' => 'applications/repository/storage/githubnotification',
|
'PhabricatorRepositoryGitHubNotification' => 'applications/repository/storage/githubnotification',
|
||||||
'PhabricatorRepositoryGitHubPostReceiveController' => 'applications/repository/controller/github-post-receive',
|
'PhabricatorRepositoryGitHubPostReceiveController' => 'applications/repository/controller/github-post-receive',
|
||||||
'PhabricatorRepositoryGitPullDaemon' => 'applications/repository/daemon/gitpull',
|
'PhabricatorRepositoryGitPullDaemon' => 'applications/repository/daemon/gitpull',
|
||||||
'PhabricatorRepositoryListController' => 'applications/repository/controller/list',
|
'PhabricatorRepositoryListController' => 'applications/repository/controller/list',
|
||||||
|
'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/svn',
|
||||||
|
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/svn',
|
||||||
'PhabricatorRepositoryType' => 'applications/repository/constants/repositorytype',
|
'PhabricatorRepositoryType' => 'applications/repository/constants/repositorytype',
|
||||||
'PhabricatorSearchAbstractDocument' => 'applications/search/index/abstractdocument',
|
'PhabricatorSearchAbstractDocument' => 'applications/search/index/abstractdocument',
|
||||||
'PhabricatorSearchBaseController' => 'applications/search/controller/base',
|
'PhabricatorSearchBaseController' => 'applications/search/controller/base',
|
||||||
|
@ -449,6 +461,8 @@ phutil_register_library_map(array(
|
||||||
'DiffusionBrowseController' => 'DiffusionController',
|
'DiffusionBrowseController' => 'DiffusionController',
|
||||||
'DiffusionBrowseFileController' => 'DiffusionController',
|
'DiffusionBrowseFileController' => 'DiffusionController',
|
||||||
'DiffusionBrowseTableView' => 'AphrontView',
|
'DiffusionBrowseTableView' => 'AphrontView',
|
||||||
|
'DiffusionCommitChangeTableView' => 'AphrontView',
|
||||||
|
'DiffusionCommitController' => 'DiffusionController',
|
||||||
'DiffusionController' => 'PhabricatorController',
|
'DiffusionController' => 'PhabricatorController',
|
||||||
'DiffusionGitBrowseQuery' => 'DiffusionBrowseQuery',
|
'DiffusionGitBrowseQuery' => 'DiffusionBrowseQuery',
|
||||||
'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery',
|
'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery',
|
||||||
|
@ -483,6 +497,8 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorDaemon' => 'PhutilDaemon',
|
'PhabricatorDaemon' => 'PhutilDaemon',
|
||||||
'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController',
|
'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController',
|
||||||
'PhabricatorDaemonController' => 'PhabricatorController',
|
'PhabricatorDaemonController' => 'PhabricatorController',
|
||||||
|
'PhabricatorDaemonTimelineConsoleController' => 'PhabricatorDaemonController',
|
||||||
|
'PhabricatorDaemonTimelineEventController' => 'PhabricatorDaemonController',
|
||||||
'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO',
|
'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO',
|
||||||
'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController',
|
'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController',
|
||||||
'PhabricatorDirectoryCategoryEditController' => 'PhabricatorDirectoryController',
|
'PhabricatorDirectoryCategoryEditController' => 'PhabricatorDirectoryController',
|
||||||
|
@ -555,18 +571,26 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorRemarkupRuleManiphest' => 'PhutilRemarkupRule',
|
'PhabricatorRemarkupRuleManiphest' => 'PhutilRemarkupRule',
|
||||||
'PhabricatorRepository' => 'PhabricatorRepositoryDAO',
|
'PhabricatorRepository' => 'PhabricatorRepositoryDAO',
|
||||||
'PhabricatorRepositoryCommit' => 'PhabricatorRepositoryDAO',
|
'PhabricatorRepositoryCommit' => 'PhabricatorRepositoryDAO',
|
||||||
|
'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
|
||||||
|
'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
|
||||||
'PhabricatorRepositoryCommitDiscoveryDaemon' => 'PhabricatorRepositoryDaemon',
|
'PhabricatorRepositoryCommitDiscoveryDaemon' => 'PhabricatorRepositoryDaemon',
|
||||||
'PhabricatorRepositoryCommitParserDaemon' => 'PhabricatorRepositoryDaemon',
|
'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
|
||||||
|
'PhabricatorRepositoryCommitParserWorker' => 'PhabricatorWorker',
|
||||||
|
'PhabricatorRepositoryCommitTaskDaemon' => 'PhabricatorRepositoryDaemon',
|
||||||
'PhabricatorRepositoryController' => 'PhabricatorController',
|
'PhabricatorRepositoryController' => 'PhabricatorController',
|
||||||
'PhabricatorRepositoryCreateController' => 'PhabricatorController',
|
'PhabricatorRepositoryCreateController' => 'PhabricatorController',
|
||||||
'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO',
|
||||||
'PhabricatorRepositoryDaemon' => 'PhabricatorDaemon',
|
'PhabricatorRepositoryDaemon' => 'PhabricatorDaemon',
|
||||||
'PhabricatorRepositoryEditController' => 'PhabricatorController',
|
'PhabricatorRepositoryEditController' => 'PhabricatorController',
|
||||||
|
'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
|
||||||
'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
|
'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
|
||||||
|
'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
|
||||||
'PhabricatorRepositoryGitHubNotification' => 'PhabricatorRepositoryDAO',
|
'PhabricatorRepositoryGitHubNotification' => 'PhabricatorRepositoryDAO',
|
||||||
'PhabricatorRepositoryGitHubPostReceiveController' => 'PhabricatorRepositoryController',
|
'PhabricatorRepositoryGitHubPostReceiveController' => 'PhabricatorRepositoryController',
|
||||||
'PhabricatorRepositoryGitPullDaemon' => 'PhabricatorRepositoryDaemon',
|
'PhabricatorRepositoryGitPullDaemon' => 'PhabricatorRepositoryDaemon',
|
||||||
'PhabricatorRepositoryListController' => 'PhabricatorController',
|
'PhabricatorRepositoryListController' => 'PhabricatorController',
|
||||||
|
'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
|
||||||
|
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
|
||||||
'PhabricatorSearchBaseController' => 'PhabricatorController',
|
'PhabricatorSearchBaseController' => 'PhabricatorController',
|
||||||
'PhabricatorSearchController' => 'PhabricatorSearchBaseController',
|
'PhabricatorSearchController' => 'PhabricatorSearchBaseController',
|
||||||
'PhabricatorSearchDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorSearchDAO' => 'PhabricatorLiskDAO',
|
||||||
|
|
|
@ -183,6 +183,8 @@ class AphrontDefaultApplicationConfiguration
|
||||||
=> 'PhabricatorProjectAffiliationEditController',
|
=> 'PhabricatorProjectAffiliationEditController',
|
||||||
),
|
),
|
||||||
|
|
||||||
|
'/r(?P<callsign>[A-Z]+)(?P<commit>[a-z0-9]+)$'
|
||||||
|
=> 'DiffusionCommitController',
|
||||||
'/diffusion/' => array(
|
'/diffusion/' => array(
|
||||||
'$' => 'DiffusionHomeController',
|
'$' => 'DiffusionHomeController',
|
||||||
'(?P<callsign>[A-Z]+)' => array(
|
'(?P<callsign>[A-Z]+)' => array(
|
||||||
|
@ -201,6 +203,8 @@ class AphrontDefaultApplicationConfiguration
|
||||||
),
|
),
|
||||||
|
|
||||||
'/daemon/' => array(
|
'/daemon/' => array(
|
||||||
|
'timeline/$' => 'PhabricatorDaemonTimelineConsoleController',
|
||||||
|
'timeline/(?P<id>\d+)/$' => 'PhabricatorDaemonTimelineEventController',
|
||||||
'$' => 'PhabricatorDaemonConsoleController',
|
'$' => 'PhabricatorDaemonConsoleController',
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ abstract class PhabricatorDaemonController extends PhabricatorController {
|
||||||
$page = $this->buildStandardPageView();
|
$page = $this->buildStandardPageView();
|
||||||
|
|
||||||
$page->setApplicationName('Daemon Console');
|
$page->setApplicationName('Daemon Console');
|
||||||
$page->setBaseURI('/');
|
$page->setBaseURI('/daemon/');
|
||||||
$page->setTitle(idx($data, 'title'));
|
$page->setTitle(idx($data, 'title'));
|
||||||
$page->setTabs(
|
$page->setTabs(
|
||||||
array(
|
array(
|
||||||
|
@ -30,6 +30,10 @@ abstract class PhabricatorDaemonController extends PhabricatorController {
|
||||||
'href' => '/daemon/',
|
'href' => '/daemon/',
|
||||||
'name' => 'Console',
|
'name' => 'Console',
|
||||||
),
|
),
|
||||||
|
'timeline' => array(
|
||||||
|
'href' => '/daemon/timeline/',
|
||||||
|
'name' => 'Timeline',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
idx($data, 'tab'));
|
idx($data, 'tab'));
|
||||||
$page->setGlyph("\xE2\x98\xAF");
|
$page->setGlyph("\xE2\x98\xAF");
|
||||||
|
|
|
@ -19,18 +19,8 @@
|
||||||
class PhabricatorDaemonConsoleController extends PhabricatorDaemonController {
|
class PhabricatorDaemonConsoleController extends PhabricatorDaemonController {
|
||||||
|
|
||||||
public function processRequest() {
|
public function processRequest() {
|
||||||
$request = $this->getRequest();
|
$tasks = id(new PhabricatorWorkerTask())->loadAllWhere(
|
||||||
|
'leaseOwner IS NOT NULL');
|
||||||
if ($request->getStr('new')) {
|
|
||||||
$task = new PhabricatorWorkerTask();
|
|
||||||
$task->setTaskClass('PhabricatorGoodForNothingWorker');
|
|
||||||
$task->setPriority(4);
|
|
||||||
$task->setFailureCount(0);
|
|
||||||
$task->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
$tasks = id(new PhabricatorWorkerTask())
|
|
||||||
->loadAll();
|
|
||||||
|
|
||||||
$rows = array();
|
$rows = array();
|
||||||
foreach ($tasks as $task) {
|
foreach ($tasks as $task) {
|
||||||
|
@ -38,29 +28,100 @@ class PhabricatorDaemonConsoleController extends PhabricatorDaemonController {
|
||||||
$task->getID(),
|
$task->getID(),
|
||||||
$task->getTaskClass(),
|
$task->getTaskClass(),
|
||||||
$task->getLeaseOwner(),
|
$task->getLeaseOwner(),
|
||||||
$task->getLeaseExpires(),
|
$task->getLeaseExpires() - time(),
|
||||||
$task->getPriority(),
|
|
||||||
$task->getFailureCount(),
|
$task->getFailureCount(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$table = new AphrontTableView($rows);
|
$leased_table = new AphrontTableView($rows);
|
||||||
$table->setHeaders(
|
$leased_table->setHeaders(
|
||||||
array(
|
array(
|
||||||
'ID',
|
'ID',
|
||||||
'Class',
|
'Class',
|
||||||
'Owner',
|
'Owner',
|
||||||
'Expries',
|
'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',
|
'Count',
|
||||||
));
|
));
|
||||||
|
$queued_table->setColumnClasses(
|
||||||
|
array(
|
||||||
|
'wide',
|
||||||
|
'n',
|
||||||
|
));
|
||||||
|
$queued_table->setNoDataString('Task queue is empty.');
|
||||||
|
|
||||||
$panel = new AphrontPanelView();
|
$queued_panel = new AphrontPanelView();
|
||||||
$panel->setHeader('Tasks');
|
$queued_panel->setHeader('Queued Tasks');
|
||||||
$panel->appendChild($table);
|
$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.');
|
||||||
|
|
||||||
|
$cursor_panel = new AphrontPanelView();
|
||||||
|
$cursor_panel->setHeader('Timeline Cursors');
|
||||||
|
$cursor_panel->appendChild($cursor_table);
|
||||||
|
|
||||||
return $this->buildStandardPageResponse(
|
return $this->buildStandardPageResponse(
|
||||||
$panel,
|
array(
|
||||||
|
$leased_panel,
|
||||||
|
$queued_panel,
|
||||||
|
$cursor_panel,
|
||||||
|
),
|
||||||
array(
|
array(
|
||||||
'title' => 'Console',
|
'title' => 'Console',
|
||||||
'tab' => 'console',
|
'tab' => 'console',
|
||||||
|
|
|
@ -7,10 +7,13 @@
|
||||||
|
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'applications/daemon/controller/base');
|
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', 'infrastructure/daemon/workers/storage/task');
|
||||||
|
phutil_require_module('phabricator', 'storage/queryfx');
|
||||||
phutil_require_module('phabricator', 'view/control/table');
|
phutil_require_module('phabricator', 'view/control/table');
|
||||||
phutil_require_module('phabricator', 'view/layout/panel');
|
phutil_require_module('phabricator', 'view/layout/panel');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'markup');
|
||||||
phutil_require_module('phutil', 'utils');
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
18
src/applications/daemon/controller/timeline/__init__.php
Normal file
18
src/applications/daemon/controller/timeline/__init__.php
Normal file
|
@ -0,0 +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/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', 'markup');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhabricatorDaemonTimelineConsoleController.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',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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');
|
|
@ -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',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
src/applications/diffusion/controller/commit/__init__.php
Normal file
14
src/applications/diffusion/controller/commit/__init__.php
Normal file
|
@ -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');
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ abstract class PhabricatorRepositoryCommitDiscoveryDaemon
|
||||||
extends PhabricatorRepositoryDaemon {
|
extends PhabricatorRepositoryDaemon {
|
||||||
|
|
||||||
private $repository;
|
private $repository;
|
||||||
|
private $commitCache = array();
|
||||||
|
|
||||||
final protected function getRepository() {
|
final protected function getRepository() {
|
||||||
return $this->repository;
|
return $this->repository;
|
||||||
|
@ -40,6 +41,56 @@ abstract class PhabricatorRepositoryCommitDiscoveryDaemon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
abstract protected function discoverCommits();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
|
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'applications/repository/daemon/base');
|
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');
|
phutil_require_source('PhabricatorRepositoryCommitDiscoveryDaemon.php');
|
||||||
|
|
|
@ -19,17 +19,14 @@
|
||||||
class PhabricatorRepositoryGitCommitDiscoveryDaemon
|
class PhabricatorRepositoryGitCommitDiscoveryDaemon
|
||||||
extends PhabricatorRepositoryCommitDiscoveryDaemon {
|
extends PhabricatorRepositoryCommitDiscoveryDaemon {
|
||||||
|
|
||||||
private $lastCommit;
|
|
||||||
private $commitCache = array();
|
|
||||||
|
|
||||||
protected function discoverCommits() {
|
protected function discoverCommits() {
|
||||||
// NOTE: PhabricatorRepositoryGitPullDaemon does the actual pulls, this
|
// NOTE: PhabricatorRepositoryGitPullDaemon does the actual pulls, this
|
||||||
// just parses HEAD.
|
// just parses HEAD.
|
||||||
|
|
||||||
$repository = $this->getRepository();
|
$repository = $this->getRepository();
|
||||||
|
|
||||||
// TODO: this should be a constant somewhere
|
$vcs = $repository->getVersionControlSystem();
|
||||||
if ($repository->getVersionControlSystem() != 'git') {
|
if ($vcs != PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) {
|
||||||
throw new Exception("Repository is not a git repository.");
|
throw new Exception("Repository is not a git repository.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,12 +38,10 @@ class PhabricatorRepositoryGitCommitDiscoveryDaemon
|
||||||
$repo_base);
|
$repo_base);
|
||||||
$commit = trim($commit);
|
$commit = trim($commit);
|
||||||
|
|
||||||
if ($commit === $this->lastCommit ||
|
if ($this->isKnownCommit($commit)) {
|
||||||
$this->isKnownCommit($commit)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->lastCommit = $commit;
|
|
||||||
$this->discoverCommit($commit);
|
$this->discoverCommit($commit);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -89,51 +84,12 @@ class PhabricatorRepositoryGitCommitDiscoveryDaemon
|
||||||
$target);
|
$target);
|
||||||
$epoch = trim($epoch);
|
$epoch = trim($epoch);
|
||||||
|
|
||||||
$commit = new PhabricatorRepositoryCommit();
|
$this->recordCommit($target, $epoch);
|
||||||
$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.
|
|
||||||
}
|
|
||||||
if (empty($insert)) {
|
if (empty($insert)) {
|
||||||
break;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,10 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'applications/repository/constants/repositorytype');
|
||||||
phutil_require_module('phabricator', 'applications/repository/daemon/commitdiscovery/base');
|
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', 'future/exec');
|
||||||
phutil_require_module('phutil', 'utils');
|
|
||||||
|
|
||||||
|
|
||||||
phutil_require_source('PhabricatorRepositoryGitCommitDiscoveryDaemon.php');
|
phutil_require_source('PhabricatorRepositoryGitCommitDiscoveryDaemon.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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');
|
|
@ -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');
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
19
src/applications/repository/daemon/committask/__init__.php
Normal file
19
src/applications/repository/daemon/committask/__init__.php
Normal file
|
@ -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');
|
|
@ -16,7 +16,16 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PhabricatorRepositoryCommitParserDaemon
|
class PhabricatorRepositoryCommitData extends PhabricatorRepositoryDAO {
|
||||||
extends PhabricatorRepositoryDaemon {
|
|
||||||
|
protected $commitID;
|
||||||
|
protected $authorName;
|
||||||
|
protected $commitMessage;
|
||||||
|
|
||||||
|
public function getConfiguration() {
|
||||||
|
return array(
|
||||||
|
self::CONFIG_TIMESTAMPS => false,
|
||||||
|
) + parent::getConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
12
src/applications/repository/storage/commitdata/__init__.php
Normal file
12
src/applications/repository/storage/commitdata/__init__.php
Normal file
|
@ -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');
|
|
@ -18,6 +18,9 @@
|
||||||
|
|
||||||
class PhabricatorRepository extends PhabricatorRepositoryDAO {
|
class PhabricatorRepository extends PhabricatorRepositoryDAO {
|
||||||
|
|
||||||
|
const TABLE_PATH = 'repository_path';
|
||||||
|
const TABLE_PATHCHANGE = 'repository_pathchange';
|
||||||
|
|
||||||
protected $phid;
|
protected $phid;
|
||||||
protected $name;
|
protected $name;
|
||||||
protected $callsign;
|
protected $callsign;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
16
src/applications/repository/worker/base/__init__.php
Normal file
16
src/applications/repository/worker/base/__init__.php
Normal file
|
@ -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');
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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');
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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');
|
|
@ -0,0 +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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class PhabricatorRepositoryCommitMessageParserWorker
|
||||||
|
extends PhabricatorRepositoryCommitParserWorker {
|
||||||
|
|
||||||
|
final protected function updateCommitData($author, $message) {
|
||||||
|
$commit = $this->commit;
|
||||||
|
|
||||||
|
$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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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');
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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');
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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');
|
|
@ -48,18 +48,19 @@ class PhabricatorTimelineIterator implements Iterator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$event = new PhabricatorTimelineEvent();
|
$event = new PhabricatorTimelineEvent('NULL');
|
||||||
$event_data = new PhabricatorTimelineEventData();
|
$event_data = new PhabricatorTimelineEventData();
|
||||||
$raw_data = queryfx_all(
|
$raw_data = queryfx_all(
|
||||||
$event->establishConnection('r'),
|
$event->establishConnection('r'),
|
||||||
'SELECT event.*, event_data.eventData eventData
|
'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
|
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',
|
ORDER BY event.id ASC LIMIT %d',
|
||||||
$event->getTableName(),
|
$event->getTableName(),
|
||||||
|
$event_data->getTableName(),
|
||||||
$this->cursor->getPosition(),
|
$this->cursor->getPosition(),
|
||||||
$this->eventTypes,
|
$this->eventTypes,
|
||||||
$event_data->getTableName(),
|
|
||||||
self::LOAD_CHUNK_SIZE);
|
self::LOAD_CHUNK_SIZE);
|
||||||
|
|
||||||
$events = $event->loadAllFromArray($raw_data);
|
$events = $event->loadAllFromArray($raw_data);
|
||||||
|
|
|
@ -21,6 +21,10 @@ class PhabricatorTimelineCursor extends PhabricatorTimelineDAO {
|
||||||
protected $name;
|
protected $name;
|
||||||
protected $position;
|
protected $position;
|
||||||
|
|
||||||
|
public function getIDKey() {
|
||||||
|
return 'name';
|
||||||
|
}
|
||||||
|
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
self::CONFIG_IDS => self::IDS_MANUAL,
|
self::CONFIG_IDS => self::IDS_MANUAL,
|
||||||
|
@ -28,4 +32,11 @@ class PhabricatorTimelineCursor extends PhabricatorTimelineDAO {
|
||||||
) + parent::getConfiguration();
|
) + parent::getConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldInsertWhenSaved() {
|
||||||
|
if ($this->position == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,11 @@ class PhabricatorWorkerTask extends PhabricatorWorkerDAO {
|
||||||
protected $taskClass;
|
protected $taskClass;
|
||||||
protected $leaseOwner;
|
protected $leaseOwner;
|
||||||
protected $leaseExpires;
|
protected $leaseExpires;
|
||||||
protected $priority;
|
|
||||||
protected $failureCount;
|
protected $failureCount;
|
||||||
|
|
||||||
private $serverTime;
|
private $serverTime;
|
||||||
private $localTime;
|
private $localTime;
|
||||||
|
private $data;
|
||||||
|
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
|
@ -53,8 +53,30 @@ class PhabricatorWorkerTask extends PhabricatorWorkerDAO {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/base');
|
phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/base');
|
||||||
|
phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/taskdata');
|
||||||
|
|
||||||
|
|
||||||
phutil_require_source('PhabricatorWorkerTask.php');
|
phutil_require_source('PhabricatorWorkerTask.php');
|
||||||
|
|
|
@ -30,14 +30,21 @@ class PhabricatorTaskmasterDaemon extends PhabricatorDaemon {
|
||||||
queryfx(
|
queryfx(
|
||||||
$conn_w,
|
$conn_w,
|
||||||
'UPDATE %T SET leaseOwner = %s, leaseExpires = UNIX_TIMESTAMP() + 15
|
'UPDATE %T SET leaseOwner = %s, leaseExpires = UNIX_TIMESTAMP() + 15
|
||||||
WHERE leaseOwner IS NULL
|
WHERE leaseOwner IS NULL LIMIT 1',
|
||||||
OR leaseExpires < UNIX_TIMESTAMP()
|
|
||||||
ORDER BY leaseOwner IS NULL, failureCount, priority
|
|
||||||
LIMIT 1',
|
|
||||||
$task_table->getTableName(),
|
$task_table->getTableName(),
|
||||||
$lease_ownership_name);
|
$lease_ownership_name);
|
||||||
$rows = $conn_w->getAffectedRows();
|
$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) {
|
if ($rows) {
|
||||||
$data = queryfx_all(
|
$data = queryfx_all(
|
||||||
$conn_w,
|
$conn_w,
|
||||||
|
@ -91,7 +98,7 @@ class PhabricatorTaskmasterDaemon extends PhabricatorDaemon {
|
||||||
queryfx(
|
queryfx(
|
||||||
$conn_w,
|
$conn_w,
|
||||||
'DELETE FROM %T WHERE taskID = %d',
|
'DELETE FROM %T WHERE taskID = %d',
|
||||||
$taskdata_table,
|
$taskdata_table->getTableName(),
|
||||||
$task->getID());
|
$task->getID());
|
||||||
}
|
}
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
|
|
Loading…
Reference in a new issue