Correct a parameter order swap in "diffusion.historyquery" for Mercurial
[phabricator.git] / src / applications / diffusion / management / DiffusionRepositoryStorageManagementPanel.php
blob2b92c73c9777e93aa5a40f5e6a7ac490bda02db9
1 <?php
3 final class DiffusionRepositoryStorageManagementPanel
4 extends DiffusionRepositoryManagementPanel {
6 const PANELKEY = 'storage';
8 public function getManagementPanelLabel() {
9 return pht('Storage');
12 public function getManagementPanelOrder() {
13 return 600;
16 public function getManagementPanelIcon() {
17 $repository = $this->getRepository();
19 if ($repository->getAlmanacServicePHID()) {
20 return 'fa-sitemap';
21 } else if ($repository->isHosted()) {
22 return 'fa-database';
23 } else {
24 return 'fa-download';
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())
37 ->setIcon('fa-book')
38 ->setHref($doc_href)
39 ->setName(pht('Cluster Documentation')));
41 return $this->newCurtainView()
42 ->setActionList($action_list);
45 public function buildManagementPanelContent() {
46 return array(
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())
58 ->setViewer($viewer);
60 if ($repository->usesLocalWorkingCopy()) {
61 $storage_path = $repository->getLocalPath();
62 } else {
63 $storage_path = phutil_tag('em', array(), pht('No Local Working Copy'));
66 $service_phid = $repository->getAlmanacServicePHID();
67 if ($service_phid) {
68 $storage_service = $viewer->renderHandle($service_phid);
69 } else {
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();
84 if ($service_phid) {
85 $service = id(new AlmanacServiceQuery())
86 ->setViewer($viewer)
87 ->withServiceTypes(
88 array(
89 AlmanacClusterRepositoryServiceType::SERVICETYPE,
91 ->withPHIDs(array($service_phid))
92 ->needActiveBindings(true)
93 ->executeOne();
94 if (!$service) {
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.'));
99 } else {
100 $service = null;
103 Javelin::initBehavior('phabricator-tooltips');
105 $rows = array();
106 if ($service) {
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()) {
112 $versions = array();
113 } else {
114 $versions = PhabricatorRepositoryWorkingCopyVersion::loadVersions(
115 $repository->getPHID());
118 $versions = mpull($versions, null, 'getDevicePHID');
120 $sort = array();
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')
137 ->setMetadata(
138 array(
139 'tip' => $binding_tip,
142 $device = $any_binding->getDevice();
144 $version = idx($versions, $device->getPHID());
145 if ($version) {
146 $version_number = $version->getRepositoryVersion();
148 $href = null;
149 if ($repository->isHosted()) {
150 $href = "/diffusion/pushlog/view/{$version_number}/";
151 } else {
152 $commit = id(new DiffusionCommitQuery())
153 ->setViewer($viewer)
154 ->withIDs(array($version_number))
155 ->executeOne();
156 if ($commit) {
157 $href = $commit->getURI();
161 if ($href) {
162 $version_number = phutil_tag(
163 'a',
164 array(
165 'href' => $href,
167 $version_number);
169 } else {
170 $version_number = '-';
173 if ($version && $version->getIsWriting()) {
174 $is_writing = id(new PHUIIconView())
175 ->setIcon('fa-pencil green');
176 } else {
177 $is_writing = id(new PHUIIconView())
178 ->setIcon('fa-pencil grey');
181 $write_properties = null;
182 if ($version) {
183 $write_properties = $version->getWriteProperties();
184 if ($write_properties) {
185 try {
186 $write_properties = phutil_json_decode($write_properties);
187 } catch (Exception $ex) {
188 $write_properties = null;
193 $last_writer = null;
194 $writer_epoch = null;
195 if ($write_properties) {
196 $writer_phid = idx($write_properties, 'userPHID');
198 if ($writer_phid) {
199 $last_writer = $viewer->renderHandle($writer_phid);
202 $writer_epoch = idx($write_properties, 'epoch');
203 if ($writer_epoch) {
204 $writer_epoch = phabricator_datetime($writer_epoch, $viewer);
208 $rows[] = array(
209 $binding_icon,
210 phutil_tag(
211 'a',
212 array(
213 'href' => $device->getURI(),
215 $device->getName()),
216 $version_number,
217 $is_writing,
218 $last_writer,
219 $writer_epoch,
224 $table = id(new AphrontTableView($rows))
225 ->setNoDataString(pht('This is not a cluster repository.'))
226 ->setHeaders(
227 array(
228 null,
229 pht('Device'),
230 pht('Version'),
231 pht('Writing'),
232 pht('Last Writer'),
233 pht('Last Write At'),
235 ->setColumnClasses(
236 array(
237 null,
238 null,
239 null,
240 'right wide',
241 null,
242 'date',
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
255 // useful.
256 return;
259 $all_protocols = array(
260 'http',
261 'https',
262 'ssh',
265 $readable_panel = $this->buildRefsStatusPanel(
266 pht('Readable Service Refs'),
267 array(
268 'neverProxy' => false,
269 'protocols' => $all_protocols,
270 'writable' => false,
273 $writable_panel = $this->buildRefsStatusPanel(
274 pht('Writable Service Refs'),
275 array(
276 'neverProxy' => false,
277 'protocols' => $all_protocols,
278 'writable' => true,
281 return array(
282 $readable_panel,
283 $writable_panel,
287 private function buildRefsStatusPanel(
288 $title,
289 $options) {
291 $repository = $this->getRepository();
292 $viewer = $this->getViewer();
294 $caught = null;
295 try {
296 $refs = $repository->getAlmanacServiceRefs($viewer, $options);
297 } catch (Exception $ex) {
298 $caught = $ex;
299 } catch (Throwable $ex) {
300 $caught = $ex;
303 $info_view = null;
304 if ($caught) {
305 $refs = array();
306 $info_view = id(new PHUIInfoView())
307 ->setErrors(
308 array(
309 phutil_escape_html_newlines($caught->getMessage()),
313 $phids = array();
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');
326 $rows = array();
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');
334 } else {
335 $writable_icon = $icon_unwritable;
336 $writable_text = pht('Read Only');
339 $rows[] = array(
340 $device_handle->renderLink(),
341 $ref->getURI(),
342 $writable_icon,
343 $writable_text,
347 $table = id(new AphrontTableView($rows))
348 ->setNoDataString(pht('No repository service refs available.'))
349 ->setHeaders(
350 array(
351 pht('Device'),
352 pht('Internal Service URI'),
353 null,
354 pht('I/O'),
356 ->setColumnClasses(
357 array(
358 null,
359 'wide',
360 'icon',
361 null,
364 $box_view = $this->newBox($title, $table);
366 if ($info_view) {
367 $box_view->setInfoView($info_view);
370 return $box_view;