1
0
Fork 0
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:
epriestley 2011-03-11 09:34:22 -08:00
parent ec084ca419
commit 8bcbeface1
42 changed files with 1359 additions and 100 deletions

View 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)
);

View file

@ -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',

View file

@ -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',
), ),

View file

@ -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");

View file

@ -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',

View file

@ -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');

View file

@ -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',
));
}
}

View 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');

View file

@ -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',
));
}
}

View file

@ -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');

View file

@ -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',
));
}
}

View 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');

View file

@ -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();
}
}

View file

@ -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();
} }

View file

@ -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');

View file

@ -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;
}
} }

View file

@ -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');

View file

@ -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);
}
}
}

View file

@ -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');

View file

@ -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');

View file

@ -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);
}
}

View 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');

View file

@ -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();
}
} }

View 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');

View file

@ -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;

View file

@ -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);
}

View 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');

View file

@ -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;
}
}

View file

@ -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');

View file

@ -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));
}
}
}

View file

@ -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');

View file

@ -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();
}
}

View file

@ -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');

View file

@ -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();
}
}

View file

@ -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');

View file

@ -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);
}
}

View file

@ -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');

View file

@ -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);

View file

@ -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;
}
} }

View file

@ -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;
}
} }

View file

@ -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');

View file

@ -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) {