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

Make the Diffusion UI vaguely usable in some cases.

This commit is contained in:
epriestley 2011-03-12 16:17:34 -08:00
parent 48b5d6d025
commit 485b5e5ded
46 changed files with 1158 additions and 66 deletions

View file

@ -40,3 +40,5 @@ create table phabricator_repository.repository_filesystem (
fileType int unsigned not null, fileType int unsigned not null,
primary key (repositoryID, parentID, svnCommit, pathID) primary key (repositoryID, parentID, svnCommit, pathID)
); );
alter table repository_filesystem add key (repositoryID, svnCommit);

View file

@ -7,6 +7,15 @@
*/ */
celerity_register_resource_map(array( celerity_register_resource_map(array(
'aphront-crumbs-view-css' =>
array(
'uri' => '/res/4408ef5f/rsrc/css/aphront/crumbs-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/crumbs-view.css',
),
'aphront-dark-console-css' => 'aphront-dark-console-css' =>
array( array(
'uri' => '/res/056b0c12/rsrc/css/aphront/dark-console.css', 'uri' => '/res/056b0c12/rsrc/css/aphront/dark-console.css',
@ -217,7 +226,7 @@ celerity_register_resource_map(array(
), ),
'maniphest-transaction-detail-css' => 'maniphest-transaction-detail-css' =>
array( array(
'uri' => '/res/658912c5/rsrc/css/application/maniphest/transaction-detail.css', 'uri' => '/res/9418efc9/rsrc/css/application/maniphest/transaction-detail.css',
'type' => 'css', 'type' => 'css',
'requires' => 'requires' =>
array( array(

View file

@ -13,6 +13,7 @@ phutil_register_library_map(array(
'AphrontAjaxResponse' => 'aphront/response/ajax', 'AphrontAjaxResponse' => 'aphront/response/ajax',
'AphrontApplicationConfiguration' => 'aphront/applicationconfiguration', 'AphrontApplicationConfiguration' => 'aphront/applicationconfiguration',
'AphrontController' => 'aphront/controller', 'AphrontController' => 'aphront/controller',
'AphrontCrumbsView' => 'view/layout/crumbs',
'AphrontDatabaseConnection' => 'storage/connection/base', 'AphrontDatabaseConnection' => 'storage/connection/base',
'AphrontDefaultApplicationConfiguration' => 'aphront/default/configuration', 'AphrontDefaultApplicationConfiguration' => 'aphront/default/configuration',
'AphrontDefaultApplicationController' => 'aphront/default/controller', 'AphrontDefaultApplicationController' => 'aphront/default/controller',
@ -142,6 +143,9 @@ phutil_register_library_map(array(
'DifferentialRevisionViewController' => 'applications/differential/controller/revisionview', 'DifferentialRevisionViewController' => 'applications/differential/controller/revisionview',
'DifferentialSubscribeController' => 'applications/differential/controller/subscribe', 'DifferentialSubscribeController' => 'applications/differential/controller/subscribe',
'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus', 'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus',
'DiffusionBranchInformation' => 'applications/diffusion/data/branch',
'DiffusionBranchQuery' => 'applications/diffusion/query/branch/base',
'DiffusionBranchTableView' => 'applications/diffusion/view/branchtable',
'DiffusionBrowseController' => 'applications/diffusion/controller/browse', 'DiffusionBrowseController' => 'applications/diffusion/controller/browse',
'DiffusionBrowseFileController' => 'applications/diffusion/controller/file', 'DiffusionBrowseFileController' => 'applications/diffusion/controller/file',
'DiffusionBrowseQuery' => 'applications/diffusion/query/browse/base', 'DiffusionBrowseQuery' => 'applications/diffusion/query/browse/base',
@ -151,6 +155,7 @@ phutil_register_library_map(array(
'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',
'DiffusionGitBranchQuery' => 'applications/diffusion/query/branch/git',
'DiffusionGitBrowseQuery' => 'applications/diffusion/query/browse/git', 'DiffusionGitBrowseQuery' => 'applications/diffusion/query/browse/git',
'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/git', 'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/git',
'DiffusionGitHistoryQuery' => 'applications/diffusion/query/history/git', 'DiffusionGitHistoryQuery' => 'applications/diffusion/query/history/git',
@ -160,8 +165,12 @@ phutil_register_library_map(array(
'DiffusionHistoryTableView' => 'applications/diffusion/view/historytable', 'DiffusionHistoryTableView' => 'applications/diffusion/view/historytable',
'DiffusionHomeController' => 'applications/diffusion/controller/home', 'DiffusionHomeController' => 'applications/diffusion/controller/home',
'DiffusionPathChange' => 'applications/diffusion/data/pathchange', 'DiffusionPathChange' => 'applications/diffusion/data/pathchange',
'DiffusionRepositoryController' => 'applications/diffusion/controller/repository',
'DiffusionRepositoryPath' => 'applications/diffusion/data/repositorypath', 'DiffusionRepositoryPath' => 'applications/diffusion/data/repositorypath',
'DiffusionRequest' => 'applications/diffusion/request/base', 'DiffusionRequest' => 'applications/diffusion/request/base',
'DiffusionSvnBrowseQuery' => 'applications/diffusion/query/browse/svn',
'DiffusionSvnHistoryQuery' => 'applications/diffusion/query/history/svn',
'DiffusionView' => 'applications/diffusion/view/base',
'Javelin' => 'infrastructure/javelin/api', 'Javelin' => 'infrastructure/javelin/api',
'LiskDAO' => 'storage/lisk/dao', 'LiskDAO' => 'storage/lisk/dao',
'ManiphestController' => 'applications/maniphest/controller/base', 'ManiphestController' => 'applications/maniphest/controller/base',
@ -364,6 +373,7 @@ phutil_register_library_map(array(
'Aphront400Response' => 'AphrontResponse', 'Aphront400Response' => 'AphrontResponse',
'Aphront404Response' => 'AphrontResponse', 'Aphront404Response' => 'AphrontResponse',
'AphrontAjaxResponse' => 'AphrontResponse', 'AphrontAjaxResponse' => 'AphrontResponse',
'AphrontCrumbsView' => 'AphrontView',
'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration', 'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration',
'AphrontDefaultApplicationController' => 'AphrontController', 'AphrontDefaultApplicationController' => 'AphrontController',
'AphrontDialogResponse' => 'AphrontResponse', 'AphrontDialogResponse' => 'AphrontResponse',
@ -459,19 +469,25 @@ phutil_register_library_map(array(
'DifferentialRevisionUpdateHistoryView' => 'AphrontView', 'DifferentialRevisionUpdateHistoryView' => 'AphrontView',
'DifferentialRevisionViewController' => 'DifferentialController', 'DifferentialRevisionViewController' => 'DifferentialController',
'DifferentialSubscribeController' => 'DifferentialController', 'DifferentialSubscribeController' => 'DifferentialController',
'DiffusionBranchTableView' => 'DiffusionView',
'DiffusionBrowseController' => 'DiffusionController', 'DiffusionBrowseController' => 'DiffusionController',
'DiffusionBrowseFileController' => 'DiffusionController', 'DiffusionBrowseFileController' => 'DiffusionController',
'DiffusionBrowseTableView' => 'AphrontView', 'DiffusionBrowseTableView' => 'DiffusionView',
'DiffusionCommitChangeTableView' => 'AphrontView', 'DiffusionCommitChangeTableView' => 'DiffusionView',
'DiffusionCommitController' => 'DiffusionController', 'DiffusionCommitController' => 'DiffusionController',
'DiffusionController' => 'PhabricatorController', 'DiffusionController' => 'PhabricatorController',
'DiffusionGitBranchQuery' => 'DiffusionBranchQuery',
'DiffusionGitBrowseQuery' => 'DiffusionBrowseQuery', 'DiffusionGitBrowseQuery' => 'DiffusionBrowseQuery',
'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery',
'DiffusionGitHistoryQuery' => 'DiffusionHistoryQuery', 'DiffusionGitHistoryQuery' => 'DiffusionHistoryQuery',
'DiffusionGitRequest' => 'DiffusionRequest', 'DiffusionGitRequest' => 'DiffusionRequest',
'DiffusionHistoryController' => 'DiffusionController', 'DiffusionHistoryController' => 'DiffusionController',
'DiffusionHistoryTableView' => 'AphrontView', 'DiffusionHistoryTableView' => 'DiffusionView',
'DiffusionHomeController' => 'DiffusionController', 'DiffusionHomeController' => 'DiffusionController',
'DiffusionRepositoryController' => 'DiffusionController',
'DiffusionSvnBrowseQuery' => 'DiffusionBrowseQuery',
'DiffusionSvnHistoryQuery' => 'DiffusionHistoryQuery',
'DiffusionView' => 'AphrontView',
'ManiphestController' => 'PhabricatorController', 'ManiphestController' => 'PhabricatorController',
'ManiphestDAO' => 'PhabricatorLiskDAO', 'ManiphestDAO' => 'PhabricatorLiskDAO',
'ManiphestTask' => 'ManiphestDAO', 'ManiphestTask' => 'ManiphestDAO',

View file

@ -187,13 +187,14 @@ class AphrontDefaultApplicationConfiguration
=> 'DiffusionCommitController', => 'DiffusionCommitController',
'/diffusion/' => array( '/diffusion/' => array(
'$' => 'DiffusionHomeController', '$' => 'DiffusionHomeController',
'(?P<callsign>[A-Z]+)' => array( '(?P<callsign>[A-Z]+)/' => array(
'/history/'. '$' => 'DiffusionRepositoryController',
'history/'.
'(?P<path>.*?)'. '(?P<path>.*?)'.
'(?:[;](?P<commit>[a-z0-9]+))?'. '(?:[;](?P<commit>[a-z0-9]+))?'.
'$' '$'
=> 'DiffusionHistoryController', => 'DiffusionHistoryController',
'/browse/'. 'browse/'.
'(?P<path>.*?)'. '(?P<path>.*?)'.
'(?:[;](?P<commit>[a-z0-9]+))?'. '(?:[;](?P<commit>[a-z0-9]+))?'.
'(?:[$](?P<line>\d+))?'. '(?:[$](?P<line>\d+))?'.

View file

@ -30,6 +30,10 @@ abstract class DiffusionController extends PhabricatorController {
return $this; return $this;
} }
protected function getDiffusionRequest() {
return $this->diffusionRequest;
}
public function buildStandardPageResponse($view, array $data) { public function buildStandardPageResponse($view, array $data) {
$page = $this->buildStandardPageView(); $page = $this->buildStandardPageView();
@ -44,4 +48,183 @@ abstract class DiffusionController extends PhabricatorController {
return $response->setContent($page->render()); return $response->setContent($page->render());
} }
final protected function buildSideNav($selected, $has_change_view) {
$nav = new AphrontSideNavView();
$navs = array(
'history' => 'History View',
'browse' => 'Browse View',
'change' => 'Change View',
);
if (!$has_change_view) {
unset($navs['change']);
}
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$callsign = $repository->getCallsign();
$branch_uri = $drequest->getBranchURIComponent($drequest->getBranch());
$path_uri = $branch_uri.$drequest->getPath();
$commit_uri = null;
$raw_commit = $drequest->getRawCommit();
if ($raw_commit) {
$commit_uri = ';'.$drequest->getCommitURIComponent($raw_commit);
}
foreach ($navs as $uri => $name) {
$nav->addNavItem(
phutil_render_tag(
'a',
array(
'href' => "/diffusion/{$callsign}/{$uri}/{$path_uri}{$commit_uri}",
'class' =>
($uri == $selected
? 'aphront-side-nav-selected'
: null),
),
$name));
}
return $nav;
}
public function buildCrumbs(array $spec = array()) {
$drequest = $this->diffusionRequest;
$crumbs = new AphrontCrumbsView();
$crumb_list = array();
$repository = $drequest->getRepository();
if ($repository) {
$crumb_list[] = phutil_render_tag(
'a',
array(
'href' => '/diffusion/',
),
'Diffusion');
} else {
$crumb_list[] = 'Diffusion';
$crumbs->setCrumbs($crumb_list);
return $crumbs;
}
$callsign = $repository->getCallsign();
$repository_name = phutil_escape_html($repository->getName()).' Repository';
$branch_name = $drequest->getBranch();
if ($branch_name) {
$repository_name .= ' ('.phutil_escape_html($branch_name).')';
}
$branch_uri = $drequest->getBranchURIComponent($drequest->getBranch());
if (empty($spec['view'])) {
$crumb_list[] = $repository_name;
$crumbs->setCrumbs($crumb_list);
return $crumbs;
}
$crumb_list[] = phutil_render_tag(
'a',
array(
'href' => "/diffusion/{$callsign}/",
),
$repository_name);
if (empty($spec['view'])) {
$crumbs->setCrumbs($crumb_list);
return $crumbs;
}
$view = $spec['view'];
switch ($view) {
case 'history':
$view_name = 'History';
break;
case 'browse':
$view_name = 'Browse';
break;
}
$path = null;
if (isset($spec['path'])) {
$path = $drequest->getPath();
}
$view_root_uri = "/diffusion/{$callsign}/{$view}/{$branch_uri}";
$jump_href = $view_root_uri;
$view_tail_uri = null;
$raw_commit = $drequest->getRawCommit();
if ($raw_commit) {
$view_tail_uri = ';'.$drequest->getCommitURIComponent($raw_commit);
}
if (!strlen($path)) {
$crumb_list[] = $view_name;
} else {
$crumb_list[] = phutil_render_tag(
'a',
array(
'href' => $view_root_uri.$view_tail_uri,
),
$view_name);
$path_parts = explode('/', $path);
do {
$last = array_pop($path_parts);
} while ($last == '');
$path_sections = array();
$thus_far = '';
foreach ($path_parts as $path_part) {
$thus_far .= $path_part.'/';
$path_sections[] = phutil_render_tag(
'a',
array(
'href' => $view_root_uri.$thus_far.$view_tail_uri,
),
phutil_escape_html($path_part));
}
$path_sections[] = phutil_escape_html($last);
$path_sections = '/'.implode('/', $path_sections);
$jump_href = $view_root_uri.$thus_far.$last;
$crumb_list[] = $path_sections;
}
$last_crumb = array_pop($crumb_list);
if ($raw_commit) {
$commit_link = DiffusionView::linkCommit(
$repository,
$raw_commit);
$jump_link = phutil_render_tag(
'a',
array(
'href' => $jump_href,
),
'Jump to HEAD');
$last_crumb .= " @ {$commit_link} ({$jump_link})";
} else {
$last_crumb .= " @ HEAD";
}
$crumb_list[] = $last_crumb;
$crumbs->setCrumbs($crumb_list);
return $crumbs;
}
} }

View file

@ -9,7 +9,11 @@
phutil_require_module('phabricator', 'aphront/response/webpage'); phutil_require_module('phabricator', 'aphront/response/webpage');
phutil_require_module('phabricator', 'applications/base/controller/base'); phutil_require_module('phabricator', 'applications/base/controller/base');
phutil_require_module('phabricator', 'applications/diffusion/request/base'); phutil_require_module('phabricator', 'applications/diffusion/request/base');
phutil_require_module('phabricator', 'applications/diffusion/view/base');
phutil_require_module('phabricator', 'view/layout/crumbs');
phutil_require_module('phabricator', 'view/layout/sidenav');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils'); phutil_require_module('phutil', 'utils');

View file

@ -26,6 +26,13 @@ class DiffusionBrowseController extends DiffusionController {
$content = array(); $content = array();
$content[] = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'browse',
));
if (!$results) { if (!$results) {
switch ($browse_query->getReasonForEmptyResultSet()) { switch ($browse_query->getReasonForEmptyResultSet()) {
@ -69,19 +76,16 @@ class DiffusionBrowseController extends DiffusionController {
$browse_table->setPaths($results); $browse_table->setPaths($results);
$browse_panel = new AphrontPanelView(); $browse_panel = new AphrontPanelView();
$browse_panel->setHeader($drequest->getPath());
$browse_panel->appendChild($browse_table); $browse_panel->appendChild($browse_table);
$content[] = $browse_panel; $content[] = $browse_panel;
// TODO: Branch table
} }
// TODO: Crumbs $nav = $this->buildSideNav('browse', false);
// TODO: Side nav $nav->appendChild($content);
return $this->buildStandardPageResponse( return $this->buildStandardPageResponse(
$content, $nav,
array( array(
'title' => basename($drequest->getPath()), 'title' => basename($drequest->getPath()),
)); ));

View file

@ -19,6 +19,15 @@
class DiffusionBrowseFileController extends DiffusionController { class DiffusionBrowseFileController extends DiffusionController {
public function processRequest() { public function processRequest() {
$content = array();
$content[] = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'browse',
));
$file_query = DiffusionFileContentQuery::newFromDiffusionRequest( $file_query = DiffusionFileContentQuery::newFromDiffusionRequest(
$this->diffusionRequest); $this->diffusionRequest);
$file_content = $file_query->loadFileContent(); $file_content = $file_query->loadFileContent();
@ -26,13 +35,19 @@ class DiffusionBrowseFileController extends DiffusionController {
$corpus = phutil_render_tag( $corpus = phutil_render_tag(
'textarea', 'textarea',
array( array(
'style' => 'margin: 1em 2em; width: 90%; height: 80em;',
), ),
phutil_escape_html($file_content->getCorpus())); phutil_escape_html($file_content->getCorpus()));
$content[] = $corpus;
// TODO: blame, color, line numbers, highlighting, etc etc // TODO: blame, color, line numbers, highlighting, etc etc
$nav = $this->buildSideNav('browse', true);
$nav->appendChild($content);
return $this->buildStandardPageResponse( return $this->buildStandardPageResponse(
$corpus, $nav,
array( array(
'title' => 'Browse', 'title' => 'Browse',
)); ));

View file

@ -28,21 +28,30 @@ class DiffusionHistoryController extends DiffusionController {
$content = array(); $content = array();
$content[] = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'history',
));
$history_table = new DiffusionHistoryTableView(); $history_table = new DiffusionHistoryTableView();
$history_table->setDiffusionRequest($drequest); $history_table->setDiffusionRequest($drequest);
$history_table->setHistory($history); $history_table->setHistory($history);
$history_panel = new AphrontPanelView(); $history_panel = new AphrontPanelView();
$history_panel->setHeader($drequest->getPath());
$history_panel->appendChild($history_table); $history_panel->appendChild($history_table);
$content[] = $history_panel; $content[] = $history_panel;
// TODO: Crumbs // TODO: Sometimes we do have a change view, we need to look at the most
// TODO: Side nav // recent history entry to figure it out.
$nav = $this->buildSideNav('history', false);
$nav->appendChild($content);
return $this->buildStandardPageResponse( return $this->buildStandardPageResponse(
$content, $nav,
array( array(
'title' => 'history', 'title' => 'history',
)); ));

View file

@ -49,7 +49,7 @@ class DiffusionHomeController extends DiffusionController {
phutil_render_tag( phutil_render_tag(
'a', 'a',
array( array(
'href' => '#', // TODO: Link 'href' => '/diffusion/'.$repository->getCallsign().'/',
), ),
phutil_escape_html($repository->getName())), phutil_escape_html($repository->getName())),
$repository->getVersionControlSystem(), $repository->getVersionControlSystem(),
@ -81,8 +81,13 @@ class DiffusionHomeController extends DiffusionController {
$panel->setHeader('Browse Repositories'); $panel->setHeader('Browse Repositories');
$panel->appendChild($table); $panel->appendChild($table);
$crumbs = $this->buildCrumbs();
return $this->buildStandardPageResponse( return $this->buildStandardPageResponse(
$panel, array(
$crumbs,
$panel,
),
array( array(
'title' => 'Diffusion', 'title' => 'Diffusion',
)); ));

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 DiffusionRepositoryController extends DiffusionController {
public function processRequest() {
$drequest = $this->diffusionRequest;
$content = array();
$crumbs = $this->buildCrumbs();
$content[] = $crumbs;
$history_query = DiffusionHistoryQuery::newFromDiffusionRequest(
$drequest);
$history_query->setLimit(15);
$history = $history_query->loadHistory();
$history_table = new DiffusionHistoryTableView();
$history_table->setDiffusionRequest($drequest);
$history_table->setHistory($history);
$panel = new AphrontPanelView();
$panel->setHeader('Recent Commits');
$panel->appendChild($history_table);
$content[] = $panel;
$browse_query = DiffusionBrowseQuery::newFromDiffusionRequest($drequest);
$results = $browse_query->loadPaths();
$browse_table = new DiffusionBrowseTableView();
$browse_table->setDiffusionRequest($drequest);
$browse_table->setPaths($results);
$browse_panel = new AphrontPanelView();
$browse_panel->setHeader('Browse Repository');
$browse_panel->appendChild($browse_table);
$content[] = $browse_panel;
if ($drequest->getBranch() !== null) {
$branch_query = DiffusionBranchQuery::newFromDiffusionRequest($drequest);
$branches = $branch_query->loadBranches();
$branch_table = new DiffusionBranchTableView();
$branch_table->setDiffusionRequest($drequest);
$branch_table->setBranches($branches);
$branch_panel = new AphrontPanelView();
$branch_panel->setHeader('Branches');
$branch_panel->appendChild($branch_table);
$content[] = $branch_panel;
}
return $this->buildStandardPageResponse(
$content,
array(
'title' => 'Diffusion',
));
}
}

View file

@ -0,0 +1,19 @@
<?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/query/branch/base');
phutil_require_module('phabricator', 'applications/diffusion/query/browse/base');
phutil_require_module('phabricator', 'applications/diffusion/query/history/base');
phutil_require_module('phabricator', 'applications/diffusion/view/branchtable');
phutil_require_module('phabricator', 'applications/diffusion/view/browsetable');
phutil_require_module('phabricator', 'applications/diffusion/view/historytable');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_source('DiffusionRepositoryController.php');

View file

@ -0,0 +1,42 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DiffusionBranchInformation {
private $name;
private $headCommitIdentifier;
public function setName($name) {
$this->name = $name;
return $this;
}
public function getName() {
return $this->name;
}
public function setHeadCommitIdentifier($head_commit_identifier) {
$this->headCommitIdentifier = $head_commit_identifier;
return $this;
}
public function getHeadCommitIdentifier() {
return $this->headCommitIdentifier;
}
}

View file

@ -0,0 +1,10 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_source('DiffusionBranchInformation.php');

View file

@ -18,15 +18,15 @@
final class DiffusionPathChange { final class DiffusionPathChange {
private $commit; private $commitIdentifier;
final public function setCommit($commit) { final public function setCommitIdentifier($commit) {
$this->commit = $commit; $this->commitIdentifier = $commit;
return $this; return $this;
} }
final public function getCommit() { final public function getCommitIdentifier() {
return $this->commit; return $this->commitIdentifier;
} }

View file

@ -0,0 +1,57 @@
<?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 DiffusionBranchQuery {
private $request;
final private function __construct() {
// <private>
}
final public static function newFromDiffusionRequest(
DiffusionRequest $request) {
$repository = $request->getRepository();
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$class = 'DiffusionGitBranchQuery';
break;
default:
throw new Exception("Unsupported VCS!");
}
PhutilSymbolLoader::loadClass($class);
$query = new $class();
$query->request = $request;
return $query;
}
final protected function getRequest() {
return $this->request;
}
final public function loadBranches() {
return $this->executeQuery();
}
abstract protected function executeQuery();
}

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/constants/repositorytype');
phutil_require_module('phutil', 'symbols');
phutil_require_source('DiffusionBranchQuery.php');

View file

@ -0,0 +1,52 @@
<?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 DiffusionGitBranchQuery extends DiffusionBranchQuery {
protected function executeQuery() {
$drequest = $this->getRequest();
$repository = $drequest->getRepository();
$path = $drequest->getPath();
$commit = $drequest->getCommit();
$local_path = $repository->getDetail('local-path');
list($stdout) = execx(
'(cd %s && git branch --verbose --no-abbrev)',
$local_path);
$branches = array();
$lines = array_filter(explode("\n", $stdout));
foreach ($lines as $line) {
$matches = null;
if (!preg_match('/^[ *] (\S+)\s+([a-z0-9]{40}) /', $line, $matches)) {
throw new Exception("Failed to parse {$line}!");
}
$branch = new DiffusionBranchInformation();
$branch->setName($matches[1]);
$branch->setHeadCommitIdentifier($matches[2]);
$branches[] = $branch;
}
return $branches;
}
}

View file

@ -0,0 +1,15 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/diffusion/data/branch');
phutil_require_module('phabricator', 'applications/diffusion/query/branch/base');
phutil_require_module('phutil', 'future/exec');
phutil_require_source('DiffusionGitBranchQuery.php');

View file

@ -39,10 +39,13 @@ abstract class DiffusionBrowseQuery {
$repository = $request->getRepository(); $repository = $request->getRepository();
switch ($repository->getVersionControlSystem()) { switch ($repository->getVersionControlSystem()) {
case 'git': case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
// TODO: Verify local-path? // TODO: Verify local-path?
$class = 'DiffusionGitBrowseQuery'; $class = 'DiffusionGitBrowseQuery';
break; break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$class = 'DiffusionSvnBrowseQuery';
break;
default: default:
throw new Exception("Unsupported VCS!"); throw new Exception("Unsupported VCS!");
} }

View file

@ -6,6 +6,8 @@
phutil_require_module('phabricator', 'applications/repository/constants/repositorytype');
phutil_require_module('phutil', 'symbols'); phutil_require_module('phutil', 'symbols');

View file

@ -0,0 +1,93 @@
<?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 DiffusionSvnBrowseQuery extends DiffusionBrowseQuery {
protected function executeQuery() {
$drequest = $this->getRequest();
$repository = $drequest->getRepository();
$path = $drequest->getPath();
$commit = $drequest->getCommit();
$path_normal = '/'.trim($path, '/');
$conn_r = $repository->establishConnection('r');
$paths = queryfx_all(
$conn_r,
'SELECT id, path FROM %T WHERE path IN (%Ls)',
PhabricatorRepository::TABLE_PATH,
array($path_normal));
$paths = ipull($paths, 'id', 'path');
$path_id = $paths[$path_normal];
$index = queryfx_all(
$conn_r,
'SELECT pathID, max(svnCommit) maxCommit FROM %T WHERE
repositoryID = %d AND parentID = %d
%Q GROUP BY pathID',
PhabricatorRepository::TABLE_FILESYSTEM,
$repository->getID(),
$path_id,
'');
if (!$index) {
// TODO: !
return false;
}
$sql = array();
foreach ($index as $row) {
$sql[] = '('.(int)$row['pathID'].', '.(int)$row['maxCommit'].')';
}
$browse = queryfx_all(
$conn_r,
'SELECT *, p.path pathName
FROM %T f JOIN %T p ON f.pathID = p.id
WHERE repositoryID = %d
AND parentID = %d
AND existed = 1
AND (pathID, svnCommit) in (%Q)
ORDER BY pathName',
PhabricatorRepository::TABLE_FILESYSTEM,
PhabricatorRepository::TABLE_PATH,
$repository->getID(),
$path_id,
implode(', ', $sql));
$results = array();
foreach ($browse as $file) {
$file_path = $file['pathName'];
$file_path = ltrim(substr($file_path, strlen($path_normal)), '/');
$result = new DiffusionRepositoryPath();
$result->setPath($file_path);
// $result->setHash($hash);
$result->setFileType($file['fileType']);
// $result->setFileSize($size);
$results[] = $result;
}
return $results;
}
}

View file

@ -0,0 +1,17 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/diffusion/data/repositorypath');
phutil_require_module('phabricator', 'applications/diffusion/query/browse/base');
phutil_require_module('phabricator', 'applications/repository/storage/repository');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phutil', 'utils');
phutil_require_source('DiffusionSvnBrowseQuery.php');

View file

@ -19,6 +19,7 @@
abstract class DiffusionHistoryQuery { abstract class DiffusionHistoryQuery {
private $request; private $request;
private $limit = 100;
final private function __construct() { final private function __construct() {
// <private> // <private>
@ -30,9 +31,12 @@ abstract class DiffusionHistoryQuery {
$repository = $request->getRepository(); $repository = $request->getRepository();
switch ($repository->getVersionControlSystem()) { switch ($repository->getVersionControlSystem()) {
case 'git': case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$class = 'DiffusionGitHistoryQuery'; $class = 'DiffusionGitHistoryQuery';
break; break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$class = 'DiffusionSvnHistoryQuery';
break;
default: default:
throw new Exception("Unsupported VCS!"); throw new Exception("Unsupported VCS!");
} }
@ -53,5 +57,14 @@ abstract class DiffusionHistoryQuery {
return $this->executeQuery(); return $this->executeQuery();
} }
final public function setLimit($limit) {
$this->limit = $limit;
return $this;
}
final public function getLimit() {
return $this->limit;
}
abstract protected function executeQuery(); abstract protected function executeQuery();
} }

View file

@ -6,6 +6,8 @@
phutil_require_module('phabricator', 'applications/repository/constants/repositorytype');
phutil_require_module('phutil', 'symbols'); phutil_require_module('phutil', 'symbols');

View file

@ -30,8 +30,8 @@ final class DiffusionGitHistoryQuery extends DiffusionHistoryQuery {
list($stdout) = execx( list($stdout) = execx(
'(cd %s && %s log '. '(cd %s && %s log '.
'-n %d '.
'--skip=%d '. '--skip=%d '.
'-n %d '.
'-M '. '-M '.
'-C '. '-C '.
'-B '. '-B '.
@ -43,8 +43,8 @@ final class DiffusionGitHistoryQuery extends DiffusionHistoryQuery {
'%s -- %s)', '%s -- %s)',
$local_path, $local_path,
$git, $git,
$limit = 100,
$offset = 0, $offset = 0,
$this->getLimit(),
$commit, $commit,
$path); $path);
@ -56,7 +56,7 @@ final class DiffusionGitHistoryQuery extends DiffusionHistoryQuery {
list($hash, $raw) = explode("\x1d", $commit); list($hash, $raw) = explode("\x1d", $commit);
$item = new DiffusionPathChange(); $item = new DiffusionPathChange();
$item->setCommit($hash); $item->setCommitIdentifier($hash);
$history[] = $item; $history[] = $item;
} }

View file

@ -0,0 +1,60 @@
<?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 DiffusionSvnHistoryQuery extends DiffusionHistoryQuery {
protected function executeQuery() {
$drequest = $this->getRequest();
$repository = $drequest->getRepository();
$path = $drequest->getPath();
$commit = $drequest->getCommit();
$conn_r = $repository->establishConnection('r');
$paths = queryfx_all(
$conn_r,
'SELECT id, path FROM %T WHERE path IN (%Ls)',
PhabricatorRepository::TABLE_PATH,
array('/'.trim($path, '/')));
$paths = ipull($paths, 'id', 'path');
$path_id = $paths['/'.trim($path, '/')];
$history_data = queryfx_all(
$conn_r,
'SELECT * FROM %T WHERE repositoryID = %d AND pathID = %d
AND commitSequence <= %d
ORDER BY commitSequence DESC
LIMIT %d',
PhabricatorRepository::TABLE_PATHCHANGE,
$repository->getID(),
$path_id,
$commit ? $commit : 0x7FFFFFFF,
$this->getLimit());
$history = array();
foreach ($history_data as $row) {
$item = new DiffusionPathChange();
$item->setCommitIdentifier($row['commitID']);
$history[] = $item;
}
return $history;
}
}

View file

@ -0,0 +1,17 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/diffusion/data/pathchange');
phutil_require_module('phabricator', 'applications/diffusion/query/history/base');
phutil_require_module('phabricator', 'applications/repository/storage/repository');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phutil', 'utils');
phutil_require_source('DiffusionSvnHistoryQuery.php');

View file

@ -99,4 +99,16 @@ class DiffusionRequest {
return $this->branch; return $this->branch;
} }
final public function getRawCommit() {
return $this->commit;
}
public function getCommitURIComponent($commit) {
return $commit;
}
public function getBranchURIComponent($branch) {
return $branch;
}
} }

View file

@ -27,6 +27,14 @@ class DiffusionGitRequest extends DiffusionRequest {
$branch = array_shift($parts); $branch = array_shift($parts);
$this->branch = $this->decodeBranchName($branch); $this->branch = $this->decodeBranchName($branch);
foreach ($parts as $key => $part) {
// Prevent any hyjinx since we're ultimately shipping this to the
// filesystem under a lot of git workflows.
if ($part == '..') {
unset($parts[$key]);
}
}
$this->path = implode('/', $parts); $this->path = implode('/', $parts);
if ($this->repository) { if ($this->repository) {
@ -96,6 +104,10 @@ class DiffusionGitRequest extends DiffusionRequest {
return $this->getBranch(); return $this->getBranch();
} }
public function getBranchURIComponent($branch) {
return $this->encodeBranchName($branch).'/';
}
private function decodeBranchName($branch) { private function decodeBranchName($branch) {
return str_replace(':', '/', $branch); return str_replace(':', '/', $branch);
} }

View file

@ -0,0 +1,109 @@
<?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 DiffusionView extends AphrontView {
private $diffusionRequest;
final public function setDiffusionRequest(DiffusionRequest $request) {
$this->diffusionRequest = $request;
return $this;
}
final public function getDiffusionRequest() {
return $this->diffusionRequest;
}
final public function linkHistory($path) {
$drequest = $this->getDiffusionRequest();
if ($drequest->getRawCommit()) {
$commit = ';'.$drequest->getCommitURIComponent($drequest->getRawCommit());
} else {
$commit = null;
}
$repository = $drequest->getRepository();
$callsign = $repository->getCallsign();
$branch = $drequest->getBranchURIComponent($drequest->getBranch());
$path = $branch.$path;
$text = 'History';
return phutil_render_tag(
'a',
array(
'href' => "/diffusion/{$callsign}/history/{$path}{$commit}",
),
$text);
}
final public function linkBrowse($path, array $details = array()) {
$drequest = $this->getDiffusionRequest();
$raw_commit = idx($details, 'commit', $drequest->getRawCommit());
if ($raw_commit) {
$commit = ';'.$drequest->getCommitURIComponent($raw_commit);
} else {
$commit = null;
}
$repository = $drequest->getRepository();
$callsign = $repository->getCallsign();
$branch = $drequest->getBranchURIComponent($drequest->getBranch());
$path = $branch.$path;
if (isset($details['text'])) {
$text = phutil_escape_html($details['text']);
} else {
$text = 'Browse';
}
return phutil_render_tag(
'a',
array(
'href' => "/diffusion/{$callsign}/browse/{$path}{$commit}",
),
$text);
}
final public static function linkCommit($repository, $commit) {
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$commit_name = substr($commit, 0, 7);
break;
default:
$commit_name = $commit;
break;
}
$callsign = $repository->getCallsign();
$commit_name = "r{$callsign}{$commit_name}";
return phutil_render_tag(
'a',
array(
'href' => "/r{$callsign}{$commit}",
),
$commit_name);
}
}

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/constants/repositorytype');
phutil_require_module('phabricator', 'view/base');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('DiffusionView.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 DiffusionBranchTableView extends DiffusionView {
private $branches;
public function setBranches(array $branches) {
$this->branches = $branches;
return $this;
}
public function render() {
$drequest = $this->getDiffusionRequest();
$current_branch = $drequest->getBranch();
$rows = array();
$rowc = array();
foreach ($this->branches as $branch) {
$rows[] = array(
phutil_escape_html($branch->getName()), // TODO: link
self::linkCommit(
$drequest->getRepository(),
$branch->getHeadCommitIdentifier()),
// TODO: etc etc
);
if ($branch->getName() == $current_branch) {
$rowc[] = 'highlighted';
} else {
$rowc[] = null;
}
}
$view = new AphrontTableView($rows);
$view->setHeaders(
array(
'Branch',
'Head',
));
$view->setColumnClasses(
array(
'wide',
));
$view->setRowClasses($rowc);
return $view->render();
}
}

View file

@ -0,0 +1,15 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/diffusion/view/base');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phutil', 'markup');
phutil_require_source('DiffusionBranchTableView.php');

View file

@ -16,35 +16,55 @@
* limitations under the License. * limitations under the License.
*/ */
final class DiffusionBrowseTableView extends AphrontView { final class DiffusionBrowseTableView extends DiffusionView {
private $request;
private $paths; private $paths;
public function setDiffusionRequest(DiffusionRequest $request) {
$this->request = $request;
return $this;
}
public function setPaths(array $paths) { public function setPaths(array $paths) {
$this->paths = $paths; $this->paths = $paths;
return $this; return $this;
} }
public function render() { public function render() {
$request = $this->getDiffusionRequest();
$base_path = trim($request->getPath(), '/');
if ($base_path) {
$base_path = $base_path.'/';
}
$rows = array(); $rows = array();
foreach ($this->paths as $path) { foreach ($this->paths as $path) {
if ($path->getFileType() == DifferentialChangeType::FILE_DIRECTORY) {
$browse_text = $path->getPath().'/';
$dir_slash = '/';
} else {
$browse_text = $path->getPath();
$dir_slash = null;
}
$rows[] = array( $rows[] = array(
phutil_escape_html($path->getPath()), // TODO: link $this->linkHistory($base_path.$path->getPath().$dir_slash),
// TODO: etc etc $this->linkBrowse(
$base_path.$path->getPath().$dir_slash,
array(
'text' => $browse_text,
)),
); );
} }
$view = new AphrontTableView($rows); $view = new AphrontTableView($rows);
$view->setHeaders( $view->setHeaders(
array( array(
'History',
'Path', 'Path',
)); ));
$view->setColumnClasses(
array(
'',
'wide pri',
));
return $view->render(); return $view->render();
} }

View file

@ -6,10 +6,9 @@
phutil_require_module('phabricator', 'view/base'); phutil_require_module('phabricator', 'applications/differential/constants/changetype');
phutil_require_module('phabricator', 'applications/diffusion/view/base');
phutil_require_module('phabricator', 'view/control/table'); phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phutil', 'markup');
phutil_require_source('DiffusionBrowseTableView.php'); phutil_require_source('DiffusionBrowseTableView.php');

View file

@ -16,16 +16,10 @@
* limitations under the License. * limitations under the License.
*/ */
final class DiffusionCommitChangeTableView extends AphrontView { final class DiffusionCommitChangeTableView extends DiffusionView {
private $request;
private $pathChanges; private $pathChanges;
public function setDiffusionRequest(DiffusionRequest $request) {
$this->request = $request;
return $this;
}
public function setPathChanges(array $path_changes) { public function setPathChanges(array $path_changes) {
$this->pathChanges = $path_changes; $this->pathChanges = $path_changes;
return $this; return $this;

View file

@ -6,7 +6,7 @@
phutil_require_module('phabricator', 'view/base'); phutil_require_module('phabricator', 'applications/diffusion/view/base');
phutil_require_module('phabricator', 'view/control/table'); phutil_require_module('phabricator', 'view/control/table');

View file

@ -16,26 +16,33 @@
* limitations under the License. * limitations under the License.
*/ */
final class DiffusionHistoryTableView extends AphrontView { final class DiffusionHistoryTableView extends DiffusionView {
private $request;
private $history; private $history;
public function setDiffusionRequest(DiffusionRequest $request) {
$this->request = $request;
return $this;
}
public function setHistory(array $history) { public function setHistory(array $history) {
$this->history = $history; $this->history = $history;
return $this; return $this;
} }
public function render() { public function render() {
$drequest = $this->getDiffusionRequest();
$rows = array(); $rows = array();
foreach ($this->history as $history) { foreach ($this->history as $history) {
$rows[] = array( $rows[] = array(
phutil_escape_html($history->getCommit()), // TODO: link $this->linkBrowse(
$drequest->getPath(),
array(
'commit' => $history->getCommitIdentifier(),
)),
self::linkCommit(
$drequest->getRepository(),
$history->getCommitIdentifier()),
'?',
'?',
'',
'',
// TODO: etc etc // TODO: etc etc
); );
} }
@ -43,7 +50,21 @@ final class DiffusionHistoryTableView extends AphrontView {
$view = new AphrontTableView($rows); $view = new AphrontTableView($rows);
$view->setHeaders( $view->setHeaders(
array( array(
'Browse',
'Commit', 'Commit',
'Change',
'Date',
'Author',
'Details',
));
$view->setColumnClasses(
array(
'',
'n',
'',
'',
'',
'wide wrap',
)); ));
return $view->render(); return $view->render();
} }

View file

@ -6,10 +6,8 @@
phutil_require_module('phabricator', 'view/base'); phutil_require_module('phabricator', 'applications/diffusion/view/base');
phutil_require_module('phabricator', 'view/control/table'); phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phutil', 'markup');
phutil_require_source('DiffusionHistoryTableView.php'); phutil_require_source('DiffusionHistoryTableView.php');

View file

@ -429,6 +429,12 @@ class PhabricatorRepositorySvnCommitChangeParserWorker
} }
} }
if ($effect['rawPath'] == '/') {
// Don't bother writing the CHILD events on '/' to the filesystem
// table; in particular, it doesn't have a meaningful parentID.
continue;
}
$existed = !DifferentialChangeType::isDeleteChangeType($type); $existed = !DifferentialChangeType::isDeleteChangeType($type);
$sql[] = qsprintf( $sql[] = qsprintf(
@ -607,9 +613,8 @@ class PhabricatorRepositorySvnCommitChangeParserWorker
} }
private function getParentPath($path) { private function getParentPath($path) {
$path = rtrim('/', $path); $path = rtrim($path, '/');
$path = dirname($path); $path = dirname($path);
$path = rtrim('/', $path);
if (!$path) { if (!$path) {
$path = '/'; $path = '/';
} }

View file

@ -28,18 +28,18 @@ abstract class AphrontView {
final protected function renderChildren() { final protected function renderChildren() {
$out = array(); $out = array();
foreach ($this->children as $child) { foreach ($this->children as $child) {
$out[] = $this->renderChild($child); $out[] = $this->renderSingleView($child);
} }
return implode('', $out); return implode('', $out);
} }
private function renderChild($child) { final protected function renderSingleView($child) {
if ($child instanceof AphrontView) { if ($child instanceof AphrontView) {
return $child->render(); return $child->render();
} else if (is_array($child)) { } else if (is_array($child)) {
$out = array(); $out = array();
foreach ($child as $element) { foreach ($child as $element) {
$out[] = $this->renderChild($element); $out[] = $this->renderSingleView($element);
} }
return implode('', $out); return implode('', $out);
} else { } else {

View file

@ -0,0 +1,50 @@
<?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 AphrontCrumbsView extends AphrontView {
private $crumbs = array();
public function setCrumbs(array $crumbs) {
$this->crumbs = $crumbs;
return;
}
public function render() {
require_celerity_resource('aphront-crumbs-view-css');
$out = array();
foreach ($this->crumbs as $crumb) {
$out[] = $this->renderSingleView($crumb);
}
$out = implode(
'<span class="aphront-crumbs-spacer">'.
"\xC2\xBB".
'</span>',
$out);
return
'<div class="aphront-crumbs-view">'.
'<div class="aphront-crumbs-content">'.
$out.
'</div>'.
'</div>';
}
}

View file

@ -0,0 +1,13 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'view/base');
phutil_require_source('AphrontCrumbsView.php');

View file

@ -0,0 +1,18 @@
/**
* @provides aphront-crumbs-view-css
*/
.aphront-crumbs-view {
margin: 1em 2em;
}
.aphront-crumbs-content {
font-size: 16px;
font-weight: bold;
color: #333;
}
.aphront-crumbs-spacer {
padding: 0 .35em;
color: #888888;
}

View file

@ -74,6 +74,10 @@
white-space: normal; white-space: normal;
} }
.aphront-table-view tr.highlighted {
background: #ffff66;
}
.aphront-table-view tr.no-data td { .aphront-table-view tr.no-data td {
padding: 1em; padding: 1em;