mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-15 11:22:40 +01:00
dd2b10b8f8
Summary: Ref T4039. Long ago these were more freely editable and there were some security concerns around creating a repository, then setting its local path to point somewhere it shouldn't. Local paths are no longer editable so there's no real reason we need to provide a uniqueness guarantee anymore, but you could still make a mistake with `bin/repository move-paths` by accident, and it's a little cleaner to pull them out into their own column with a key. (We still don't -- and, largely can't -- guarantee that two paths aren't //equivalent// since one might be symlinked to the other, or symlinked only on some hosts, or whatever, but the primary value here is as a sanity check that you aren't goofing things up and pointing a bunch of repositories at the same working copy by mistake.) Test Plan: - Ran migrations. - Grepped for `local-path`. - Listed and moved paths with `bin/repository`. - Created a new repository, verified its local path populated correctly. Reviewers: chad Reviewed By: chad Maniphest Tasks: T4039 Differential Revision: https://secure.phabricator.com/D15837
235 lines
6.3 KiB
PHP
235 lines
6.3 KiB
PHP
<?php
|
|
|
|
final class DiffusionRepositoryStorageManagementPanel
|
|
extends DiffusionRepositoryManagementPanel {
|
|
|
|
const PANELKEY = 'storage';
|
|
|
|
public function getManagementPanelLabel() {
|
|
return pht('Storage');
|
|
}
|
|
|
|
public function getManagementPanelOrder() {
|
|
return 600;
|
|
}
|
|
|
|
public function getManagementPanelIcon() {
|
|
$repository = $this->getRepository();
|
|
|
|
if ($repository->getAlmanacServicePHID()) {
|
|
return 'fa-sitemap';
|
|
} else if ($repository->isHosted()) {
|
|
return 'fa-folder';
|
|
} else {
|
|
return 'fa-download';
|
|
}
|
|
}
|
|
|
|
public function buildManagementPanelContent() {
|
|
return array(
|
|
$this->buildStorageStatusPanel(),
|
|
$this->buildClusterStatusPanel(),
|
|
);
|
|
}
|
|
|
|
private function buildStorageStatusPanel() {
|
|
$repository = $this->getRepository();
|
|
$viewer = $this->getViewer();
|
|
|
|
$view = id(new PHUIPropertyListView())
|
|
->setViewer($viewer);
|
|
|
|
if ($repository->usesLocalWorkingCopy()) {
|
|
$storage_path = $repository->getLocalPath();
|
|
} else {
|
|
$storage_path = phutil_tag('em', array(), pht('No Local Working Copy'));
|
|
}
|
|
|
|
$service_phid = $repository->getAlmanacServicePHID();
|
|
if ($service_phid) {
|
|
$storage_service = $viewer->renderHandle($service_phid);
|
|
} else {
|
|
$storage_service = phutil_tag('em', array(), pht('Local'));
|
|
}
|
|
|
|
$view->addProperty(pht('Storage Path'), $storage_path);
|
|
$view->addProperty(pht('Storage Cluster'), $storage_service);
|
|
|
|
$header = id(new PHUIHeaderView())
|
|
->setHeader(pht('Storage'));
|
|
|
|
return id(new PHUIObjectBoxView())
|
|
->setHeader($header)
|
|
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
|
->addPropertyList($view);
|
|
}
|
|
|
|
private function buildClusterStatusPanel() {
|
|
$repository = $this->getRepository();
|
|
$viewer = $this->getViewer();
|
|
|
|
$service_phid = $repository->getAlmanacServicePHID();
|
|
if ($service_phid) {
|
|
$service = id(new AlmanacServiceQuery())
|
|
->setViewer($viewer)
|
|
->withServiceTypes(
|
|
array(
|
|
AlmanacClusterRepositoryServiceType::SERVICETYPE,
|
|
))
|
|
->withPHIDs(array($service_phid))
|
|
->needBindings(true)
|
|
->executeOne();
|
|
if (!$service) {
|
|
// TODO: Viewer may not have permission to see the service, or it may
|
|
// be invalid? Raise some more useful error here?
|
|
throw new Exception(pht('Unable to load cluster service.'));
|
|
}
|
|
} else {
|
|
$service = null;
|
|
}
|
|
|
|
Javelin::initBehavior('phabricator-tooltips');
|
|
|
|
$rows = array();
|
|
if ($service) {
|
|
$bindings = $service->getBindings();
|
|
$bindings = mgroup($bindings, 'getDevicePHID');
|
|
|
|
// This is an unusual read which always comes from the master.
|
|
if (PhabricatorEnv::isReadOnly()) {
|
|
$versions = array();
|
|
} else {
|
|
$versions = PhabricatorRepositoryWorkingCopyVersion::loadVersions(
|
|
$repository->getPHID());
|
|
}
|
|
|
|
$versions = mpull($versions, null, 'getDevicePHID');
|
|
|
|
foreach ($bindings as $binding_group) {
|
|
$all_disabled = true;
|
|
foreach ($binding_group as $binding) {
|
|
if (!$binding->getIsDisabled()) {
|
|
$all_disabled = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
$any_binding = head($binding_group);
|
|
|
|
if ($all_disabled) {
|
|
$binding_icon = 'fa-times grey';
|
|
$binding_tip = pht('Disabled');
|
|
} else {
|
|
$binding_icon = 'fa-folder-open green';
|
|
$binding_tip = pht('Active');
|
|
}
|
|
|
|
$binding_icon = id(new PHUIIconView())
|
|
->setIcon($binding_icon)
|
|
->addSigil('has-tooltip')
|
|
->setMetadata(
|
|
array(
|
|
'tip' => $binding_tip,
|
|
));
|
|
|
|
$device = $any_binding->getDevice();
|
|
|
|
$version = idx($versions, $device->getPHID());
|
|
if ($version) {
|
|
$version_number = $version->getRepositoryVersion();
|
|
$version_number = phutil_tag(
|
|
'a',
|
|
array(
|
|
'href' => "/diffusion/pushlog/view/{$version_number}/",
|
|
),
|
|
$version_number);
|
|
} else {
|
|
$version_number = '-';
|
|
}
|
|
|
|
if ($version && $version->getIsWriting()) {
|
|
$is_writing = id(new PHUIIconView())
|
|
->setIcon('fa-pencil green');
|
|
} else {
|
|
$is_writing = id(new PHUIIconView())
|
|
->setIcon('fa-pencil grey');
|
|
}
|
|
|
|
$write_properties = null;
|
|
if ($version) {
|
|
$write_properties = $version->getWriteProperties();
|
|
if ($write_properties) {
|
|
try {
|
|
$write_properties = phutil_json_decode($write_properties);
|
|
} catch (Exception $ex) {
|
|
$write_properties = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($write_properties) {
|
|
$writer_phid = idx($write_properties, 'userPHID');
|
|
$last_writer = $viewer->renderHandle($writer_phid);
|
|
|
|
$writer_epoch = idx($write_properties, 'epoch');
|
|
$writer_epoch = phabricator_datetime($writer_epoch, $viewer);
|
|
} else {
|
|
$last_writer = null;
|
|
$writer_epoch = null;
|
|
}
|
|
|
|
$rows[] = array(
|
|
$binding_icon,
|
|
phutil_tag(
|
|
'a',
|
|
array(
|
|
'href' => $device->getURI(),
|
|
),
|
|
$device->getName()),
|
|
$version_number,
|
|
$is_writing,
|
|
$last_writer,
|
|
$writer_epoch,
|
|
);
|
|
}
|
|
}
|
|
|
|
$table = id(new AphrontTableView($rows))
|
|
->setNoDataString(pht('This is not a cluster repository.'))
|
|
->setHeaders(
|
|
array(
|
|
null,
|
|
pht('Device'),
|
|
pht('Version'),
|
|
pht('Writing'),
|
|
pht('Last Writer'),
|
|
pht('Last Write At'),
|
|
))
|
|
->setColumnClasses(
|
|
array(
|
|
null,
|
|
null,
|
|
null,
|
|
'right wide',
|
|
null,
|
|
'date',
|
|
));
|
|
|
|
$doc_href = PhabricatorEnv::getDoclink('Cluster: Repositories');
|
|
|
|
$header = id(new PHUIHeaderView())
|
|
->setHeader(pht('Cluster Status'))
|
|
->addActionLink(
|
|
id(new PHUIButtonView())
|
|
->setIcon('fa-book')
|
|
->setHref($doc_href)
|
|
->setTag('a')
|
|
->setText(pht('Documentation')));
|
|
|
|
return id(new PHUIObjectBoxView())
|
|
->setHeader($header)
|
|
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
|
->setTable($table);
|
|
}
|
|
|
|
}
|