3 final class DiffusionRepositoryStorageManagementPanel
4 extends DiffusionRepositoryManagementPanel
{
6 const PANELKEY
= 'storage';
8 public function getManagementPanelLabel() {
12 public function getManagementPanelOrder() {
16 public function getManagementPanelIcon() {
17 $repository = $this->getRepository();
19 if ($repository->getAlmanacServicePHID()) {
21 } else if ($repository->isHosted()) {
28 public function buildManagementPanelCurtain() {
29 $repository = $this->getRepository();
30 $viewer = $this->getViewer();
31 $action_list = $this->newActionList();
33 $doc_href = PhabricatorEnv
::getDoclink('Cluster: Repositories');
35 $action_list->addAction(
36 id(new PhabricatorActionView())
39 ->setName(pht('Cluster Documentation')));
41 return $this->newCurtainView()
42 ->setActionList($action_list);
45 public function buildManagementPanelContent() {
47 $this->buildStorageStatusPanel(),
48 $this->buildClusterStatusPanel(),
49 $this->buildRefsStatusPanels(),
53 private function buildStorageStatusPanel() {
54 $repository = $this->getRepository();
55 $viewer = $this->getViewer();
57 $view = id(new PHUIPropertyListView())
60 if ($repository->usesLocalWorkingCopy()) {
61 $storage_path = $repository->getLocalPath();
63 $storage_path = phutil_tag('em', array(), pht('No Local Working Copy'));
66 $service_phid = $repository->getAlmanacServicePHID();
68 $storage_service = $viewer->renderHandle($service_phid);
70 $storage_service = phutil_tag('em', array(), pht('Local'));
73 $view->addProperty(pht('Storage Path'), $storage_path);
74 $view->addProperty(pht('Storage Cluster'), $storage_service);
76 return $this->newBox(pht('Storage'), $view);
79 private function buildClusterStatusPanel() {
80 $repository = $this->getRepository();
81 $viewer = $this->getViewer();
83 $service_phid = $repository->getAlmanacServicePHID();
85 $service = id(new AlmanacServiceQuery())
89 AlmanacClusterRepositoryServiceType
::SERVICETYPE
,
91 ->withPHIDs(array($service_phid))
92 ->needActiveBindings(true)
95 // TODO: Viewer may not have permission to see the service, or it may
96 // be invalid? Raise some more useful error here?
97 throw new Exception(pht('Unable to load cluster service.'));
103 Javelin
::initBehavior('phabricator-tooltips');
107 $bindings = $service->getActiveBindings();
108 $bindings = mgroup($bindings, 'getDevicePHID');
110 // This is an unusual read which always comes from the master.
111 if (PhabricatorEnv
::isReadOnly()) {
114 $versions = PhabricatorRepositoryWorkingCopyVersion
::loadVersions(
115 $repository->getPHID());
118 $versions = mpull($versions, null, 'getDevicePHID');
121 foreach ($bindings as $key => $binding_group) {
122 $sort[$key] = id(new PhutilSortVector())
123 ->addString(head($binding_group)->getDevice()->getName());
125 $sort = msortv($sort, 'getSelf');
126 $bindings = array_select_keys($bindings, array_keys($sort)) +
$bindings;
128 foreach ($bindings as $binding_group) {
129 $any_binding = head($binding_group);
131 $binding_icon = 'fa-folder-open green';
132 $binding_tip = pht('Active');
134 $binding_icon = id(new PHUIIconView())
135 ->setIcon($binding_icon)
136 ->addSigil('has-tooltip')
139 'tip' => $binding_tip,
142 $device = $any_binding->getDevice();
144 $version = idx($versions, $device->getPHID());
146 $version_number = $version->getRepositoryVersion();
149 if ($repository->isHosted()) {
150 $href = "/diffusion/pushlog/view/{$version_number}/";
152 $commit = id(new DiffusionCommitQuery())
154 ->withIDs(array($version_number))
157 $href = $commit->getURI();
162 $version_number = phutil_tag(
170 $version_number = '-';
173 if ($version && $version->getIsWriting()) {
174 $is_writing = id(new PHUIIconView())
175 ->setIcon('fa-pencil green');
177 $is_writing = id(new PHUIIconView())
178 ->setIcon('fa-pencil grey');
181 $write_properties = null;
183 $write_properties = $version->getWriteProperties();
184 if ($write_properties) {
186 $write_properties = phutil_json_decode($write_properties);
187 } catch (Exception
$ex) {
188 $write_properties = null;
194 $writer_epoch = null;
195 if ($write_properties) {
196 $writer_phid = idx($write_properties, 'userPHID');
199 $last_writer = $viewer->renderHandle($writer_phid);
202 $writer_epoch = idx($write_properties, 'epoch');
204 $writer_epoch = phabricator_datetime($writer_epoch, $viewer);
213 'href' => $device->getURI(),
224 $table = id(new AphrontTableView($rows))
225 ->setNoDataString(pht('This is not a cluster repository.'))
233 pht('Last Write At'),
245 return $this->newBox(pht('Cluster Status'), $table);
248 private function buildRefsStatusPanels() {
249 $repository = $this->getRepository();
251 $service_phid = $repository->getAlmanacServicePHID();
252 if (!$service_phid) {
253 // If this repository isn't clustered, don't bother rendering anything.
254 // There are enough other context clues that another empty panel isn't
259 $all_protocols = array(
265 $readable_panel = $this->buildRefsStatusPanel(
266 pht('Readable Service Refs'),
268 'neverProxy' => false,
269 'protocols' => $all_protocols,
273 $writable_panel = $this->buildRefsStatusPanel(
274 pht('Writable Service Refs'),
276 'neverProxy' => false,
277 'protocols' => $all_protocols,
287 private function buildRefsStatusPanel(
291 $repository = $this->getRepository();
292 $viewer = $this->getViewer();
296 $refs = $repository->getAlmanacServiceRefs($viewer, $options);
297 } catch (Exception
$ex) {
299 } catch (Throwable
$ex) {
306 $info_view = id(new PHUIInfoView())
309 phutil_escape_html_newlines($caught->getMessage()),
314 foreach ($refs as $ref) {
315 $phids[] = $ref->getDevicePHID();
318 $handles = $viewer->loadHandles($phids);
320 $icon_writable = id(new PHUIIconView())
321 ->setIcon('fa-pencil', 'green');
323 $icon_unwritable = id(new PHUIIconView())
324 ->setIcon('fa-times', 'grey');
327 foreach ($refs as $ref) {
328 $device_phid = $ref->getDevicePHID();
329 $device_handle = $handles[$device_phid];
331 if ($ref->isWritable()) {
332 $writable_icon = $icon_writable;
333 $writable_text = pht('Read/Write');
335 $writable_icon = $icon_unwritable;
336 $writable_text = pht('Read Only');
340 $device_handle->renderLink(),
347 $table = id(new AphrontTableView($rows))
348 ->setNoDataString(pht('No repository service refs available.'))
352 pht('Internal Service URI'),
364 $box_view = $this->newBox($title, $table);
367 $box_view->setInfoView($info_view);