@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at upstream/main 822 lines 27 kB view raw
1<?php 2 3final class DiffusionRepositoryBasicsManagementPanel 4 extends DiffusionRepositoryManagementPanel { 5 6 const PANELKEY = 'basics'; 7 8 public function getManagementPanelLabel() { 9 return pht('Basics'); 10 } 11 12 public function getManagementPanelOrder() { 13 return 100; 14 } 15 16 public function getManagementPanelIcon() { 17 return 'fa-code'; 18 } 19 20 protected function getEditEngineFieldKeys() { 21 return array( 22 'name', 23 'callsign', 24 'shortName', 25 'description', 26 'projectPHIDs', 27 ); 28 } 29 30 public function buildManagementPanelCurtain() { 31 $repository = $this->getRepository(); 32 $viewer = $this->getViewer(); 33 34 $action_list = $this->newActionList(); 35 36 $can_edit = PhabricatorPolicyFilter::hasCapability( 37 $viewer, 38 $repository, 39 PhabricatorPolicyCapability::CAN_EDIT); 40 41 $edit_uri = $this->getEditPageURI(); 42 $activate_uri = $repository->getPathURI('edit/activate/'); 43 $delete_uri = $repository->getPathURI('edit/delete/'); 44 $encoding_uri = $this->getEditPageURI('encoding'); 45 $dangerous_uri = $repository->getPathURI('edit/dangerous/'); 46 $enormous_uri = $repository->getPathURI('edit/enormous/'); 47 $update_uri = $repository->getPathURI('edit/update/'); 48 $publish_uri = $repository->getPathURI('edit/publish/'); 49 50 if ($repository->isTracked()) { 51 $activate_icon = 'fa-ban'; 52 $activate_label = pht('Deactivate Repository'); 53 } else { 54 $activate_icon = 'fa-check'; 55 $activate_label = pht('Activate Repository'); 56 } 57 58 if (!$repository->isPublishingDisabled()) { 59 $publish_icon = 'fa-ban'; 60 $publish_label = pht('Disable Publishing'); 61 } else { 62 $publish_icon = 'fa-check'; 63 $publish_label = pht('Enable Publishing'); 64 } 65 66 $should_dangerous = $repository->shouldAllowDangerousChanges(); 67 if ($should_dangerous) { 68 $dangerous_icon = 'fa-shield'; 69 $dangerous_name = pht('Prevent Dangerous Changes'); 70 $can_dangerous = $can_edit; 71 } else { 72 $dangerous_icon = 'fa-exclamation-triangle'; 73 $dangerous_name = pht('Allow Dangerous Changes'); 74 $can_dangerous = ($can_edit && $repository->canAllowDangerousChanges()); 75 } 76 77 $should_enormous = $repository->shouldAllowEnormousChanges(); 78 if ($should_enormous) { 79 $enormous_icon = 'fa-shield'; 80 $enormous_name = pht('Prevent Enormous Changes'); 81 $can_enormous = $can_edit; 82 } else { 83 $enormous_icon = 'fa-exclamation-triangle'; 84 $enormous_name = pht('Allow Enormous Changes'); 85 $can_enormous = ($can_edit && $repository->canAllowEnormousChanges()); 86 } 87 88 $action_list->addAction( 89 id(new PhabricatorActionView()) 90 ->setName(pht('Edit Basic Information')) 91 ->setHref($edit_uri) 92 ->setIcon('fa-pencil') 93 ->setDisabled(!$can_edit) 94 ->setWorkflow(!$can_edit)); 95 96 $action_list->addAction( 97 id(new PhabricatorActionView()) 98 ->setName(pht('Edit Text Encoding')) 99 ->setIcon('fa-text-width') 100 ->setHref($encoding_uri) 101 ->setDisabled(!$can_edit) 102 ->setWorkflow(!$can_edit)); 103 104 $action_list->addAction( 105 id(new PhabricatorActionView()) 106 ->setName($dangerous_name) 107 ->setHref($dangerous_uri) 108 ->setIcon($dangerous_icon) 109 ->setDisabled(!$can_dangerous) 110 ->setWorkflow(true)); 111 112 $action_list->addAction( 113 id(new PhabricatorActionView()) 114 ->setName($enormous_name) 115 ->setHref($enormous_uri) 116 ->setIcon($enormous_icon) 117 ->setDisabled(!$can_enormous) 118 ->setWorkflow(true)); 119 120 $action_list->addAction( 121 id(new PhabricatorActionView()) 122 ->setType(PhabricatorActionView::TYPE_DIVIDER)); 123 124 $action_list->addAction( 125 id(new PhabricatorActionView()) 126 ->setName($activate_label) 127 ->setHref($activate_uri) 128 ->setIcon($activate_icon) 129 ->setDisabled(!$can_edit) 130 ->setWorkflow(true)); 131 132 $action_list->addAction( 133 id(new PhabricatorActionView()) 134 ->setName($publish_label) 135 ->setHref($publish_uri) 136 ->setIcon($publish_icon) 137 ->setDisabled(!$can_edit) 138 ->setWorkflow(true)); 139 140 $action_list->addAction( 141 id(new PhabricatorActionView()) 142 ->setName(pht('Update Now')) 143 ->setHref($update_uri) 144 ->setIcon('fa-refresh') 145 ->setWorkflow(true) 146 ->setDisabled(!$can_edit)); 147 148 $action_list->addAction( 149 id(new PhabricatorActionView()) 150 ->setType(PhabricatorActionView::TYPE_DIVIDER)); 151 152 $action_list->addAction( 153 id(new PhabricatorActionView()) 154 ->setName(pht('Delete Repository')) 155 ->setHref($delete_uri) 156 ->setIcon('fa-times') 157 ->setWorkflow(true) 158 ->setDisabled(!$can_edit)); 159 160 return $this->newCurtainView() 161 ->setActionList($action_list); 162 } 163 164 public function buildManagementPanelContent() { 165 $basics = $this->buildBasics(); 166 $basics = $this->newBox(pht('Properties'), $basics); 167 168 $repository = $this->getRepository(); 169 170 $state = $this->buildStateView($repository); 171 172 $is_new = $repository->isNewlyInitialized(); 173 $info_view = null; 174 if ($is_new) { 175 $messages = array(); 176 177 $messages[] = pht( 178 'This newly created repository is not active yet. Configure policies, '. 179 'options, and URIs. When ready, %s the repository.', 180 phutil_tag('strong', array(), pht('Activate'))); 181 182 if ($repository->isHosted()) { 183 $messages[] = pht( 184 'If activated now, this repository will become a new hosted '. 185 'repository. To observe an existing repository instead, configure '. 186 'it in the %s panel.', 187 phutil_tag('strong', array(), pht('URIs'))); 188 } else { 189 $messages[] = pht( 190 'If activated now, this repository will observe an existing remote '. 191 'repository and begin importing changes.'); 192 } 193 194 $info_view = id(new PHUIInfoView()) 195 ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) 196 ->setErrors($messages); 197 } 198 199 $description = $this->buildDescription(); 200 if ($description) { 201 $description = $this->newBox(pht('Description'), $description); 202 } 203 $status = $this->buildStatus(); 204 205 return array($info_view, $state, $basics, $description, $status); 206 } 207 208 private function buildBasics() { 209 $repository = $this->getRepository(); 210 $viewer = $this->getViewer(); 211 212 $view = id(new PHUIPropertyListView()) 213 ->setViewer($viewer); 214 215 $name = $repository->getName(); 216 $view->addProperty(pht('Name'), $name); 217 218 $type = PhabricatorRepositoryType::getNameForRepositoryType( 219 $repository->getVersionControlSystem()); 220 $view->addProperty(pht('Type'), $type); 221 222 $callsign = $repository->getCallsign(); 223 if (!phutil_nonempty_string($callsign)) { 224 $callsign = phutil_tag('em', array(), pht('No Callsign')); 225 } 226 $view->addProperty(pht('Callsign'), $callsign); 227 228 $short_name = $repository->getRepositorySlug(); 229 if ($short_name === null) { 230 $short_name = phutil_tag('em', array(), pht('No Short Name')); 231 } 232 $view->addProperty(pht('Short Name'), $short_name); 233 234 $encoding = $repository->getDetail('encoding'); 235 if (!$encoding) { 236 $encoding = phutil_tag('em', array(), pht('Use Default (UTF-8)')); 237 } 238 $view->addProperty(pht('Encoding'), $encoding); 239 240 $can_dangerous = $repository->canAllowDangerousChanges(); 241 if (!$can_dangerous) { 242 $dangerous = phutil_tag('em', array(), pht('Not Preventable')); 243 } else { 244 $should_dangerous = $repository->shouldAllowDangerousChanges(); 245 if ($should_dangerous) { 246 $dangerous = pht('Allowed'); 247 } else { 248 $dangerous = pht('Not Allowed'); 249 } 250 } 251 252 $view->addProperty(pht('Dangerous Changes'), $dangerous); 253 254 $can_enormous = $repository->canAllowEnormousChanges(); 255 if (!$can_enormous) { 256 $enormous = phutil_tag('em', array(), pht('Not Preventable')); 257 } else { 258 $should_enormous = $repository->shouldAllowEnormousChanges(); 259 if ($should_enormous) { 260 $enormous = pht('Allowed'); 261 } else { 262 $enormous = pht('Not Allowed'); 263 } 264 } 265 266 $view->addProperty(pht('Enormous Changes'), $enormous); 267 268 return $view; 269 } 270 271 272 private function buildDescription() { 273 $repository = $this->getRepository(); 274 $viewer = $this->getViewer(); 275 276 $description = $repository->getDetail('description'); 277 278 $view = id(new PHUIPropertyListView()) 279 ->setViewer($viewer); 280 if (!strlen($description)) { 281 return null; 282 } else { 283 $description = new PHUIRemarkupView($viewer, $description); 284 } 285 $view->addTextContent($description); 286 287 return $view; 288 } 289 290 private function buildStatus() { 291 $repository = $this->getRepository(); 292 $viewer = $this->getViewer(); 293 294 $view = id(new PHUIPropertyListView()) 295 ->setViewer($viewer); 296 297 $view->addProperty( 298 pht('Update Frequency'), 299 $this->buildRepositoryUpdateInterval($repository)); 300 301 $messages = $this->loadStatusMessages($repository); 302 303 $status = $this->buildRepositoryStatus($repository, $messages); 304 $raw_error = $this->buildRepositoryRawError($repository, $messages); 305 306 $view->addProperty(pht('Status'), $status); 307 if ($raw_error) { 308 $view->addSectionHeader(pht('Raw Error')); 309 $view->addTextContent($raw_error); 310 } 311 312 return $this->newBox(pht('Working Copy Status'), $view); 313 } 314 315 private function buildRepositoryUpdateInterval( 316 PhabricatorRepository $repository) { 317 318 $smart_wait = $repository->loadUpdateInterval(); 319 320 $doc_href = PhabricatorEnv::getDoclink( 321 'Diffusion User Guide: Repository Updates'); 322 323 return array( 324 phutil_format_relative_time_detailed($smart_wait), 325 " \xC2\xB7 ", 326 phutil_tag( 327 'a', 328 array( 329 'href' => $doc_href, 330 'target' => '_blank', 331 ), 332 pht('Learn More')), 333 ); 334 } 335 336 private function buildRepositoryStatus( 337 PhabricatorRepository $repository, 338 array $messages) { 339 340 $viewer = $this->getViewer(); 341 $is_cluster = $repository->getAlmanacServicePHID(); 342 343 $view = new PHUIStatusListView(); 344 345 if ($repository->isTracked()) { 346 $view->addItem( 347 id(new PHUIStatusItemView()) 348 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 349 ->setTarget(pht('Repository Active'))); 350 } else { 351 $view->addItem( 352 id(new PHUIStatusItemView()) 353 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'bluegrey') 354 ->setTarget(pht('Repository Inactive')) 355 ->setNote( 356 pht('Activate this repository to begin or resume import.'))); 357 return $view; 358 } 359 360 $binaries = array(); 361 $svnlook_check = false; 362 switch ($repository->getVersionControlSystem()) { 363 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 364 $binaries[] = 'git'; 365 break; 366 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 367 $binaries[] = 'svn'; 368 break; 369 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 370 $binaries[] = 'hg'; 371 break; 372 } 373 374 if ($repository->isHosted()) { 375 $proto_https = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_HTTPS; 376 $proto_http = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_HTTP; 377 $can_http = $repository->canServeProtocol($proto_http, false) || 378 $repository->canServeProtocol($proto_https, false); 379 380 if ($can_http) { 381 switch ($repository->getVersionControlSystem()) { 382 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 383 $binaries[] = 'git-http-backend'; 384 break; 385 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 386 $binaries[] = 'svnserve'; 387 $binaries[] = 'svnadmin'; 388 $binaries[] = 'svnlook'; 389 $svnlook_check = true; 390 break; 391 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 392 $binaries[] = 'hg'; 393 break; 394 } 395 } 396 397 398 $proto_ssh = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_SSH; 399 $can_ssh = $repository->canServeProtocol($proto_ssh, false); 400 401 if ($can_ssh) { 402 switch ($repository->getVersionControlSystem()) { 403 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 404 $binaries[] = 'git-receive-pack'; 405 $binaries[] = 'git-upload-pack'; 406 break; 407 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 408 $binaries[] = 'svnserve'; 409 $binaries[] = 'svnadmin'; 410 $binaries[] = 'svnlook'; 411 $svnlook_check = true; 412 break; 413 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 414 $binaries[] = 'hg'; 415 break; 416 } 417 } 418 } 419 420 $binaries = array_unique($binaries); 421 if (!$is_cluster) { 422 // We're only checking for binaries if we aren't running with a cluster 423 // configuration. In theory, we could check for binaries on the 424 // repository host machine, but we'd need to make this more complicated 425 // to do that. 426 427 foreach ($binaries as $binary) { 428 $where = Filesystem::resolveBinary($binary); 429 if (!$where) { 430 $view->addItem( 431 id(new PHUIStatusItemView()) 432 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 433 ->setTarget( 434 pht('Missing Binary %s', phutil_tag('tt', array(), $binary))) 435 ->setNote(pht( 436 "Unable to find this binary in the webserver's PATH. You may ". 437 "need to configure %s.", 438 $this->getEnvConfigLink()))); 439 } else { 440 $view->addItem( 441 id(new PHUIStatusItemView()) 442 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 443 ->setTarget( 444 pht('Found Binary %s', phutil_tag('tt', array(), $binary))) 445 ->setNote(phutil_tag('tt', array(), $where))); 446 } 447 } 448 449 // This gets checked generically above. However, for svn commit hooks, we 450 // need this to be in environment.append-paths because subversion strips 451 // PATH. 452 if ($svnlook_check) { 453 $where = Filesystem::resolveBinary('svnlook'); 454 if ($where) { 455 $path = substr($where, 0, strlen($where) - strlen('svnlook')); 456 $dirs = PhabricatorEnv::getEnvConfig('environment.append-paths'); 457 $in_path = false; 458 foreach ($dirs as $dir) { 459 if (Filesystem::isDescendant($path, $dir)) { 460 $in_path = true; 461 break; 462 } 463 } 464 if (!$in_path) { 465 $view->addItem( 466 id(new PHUIStatusItemView()) 467 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 468 ->setTarget( 469 pht('Commit Hooks: %s', phutil_tag('tt', array(), $binary))) 470 ->setNote( 471 pht( 472 'The directory containing the "svnlook" binary is not '. 473 'listed in "environment.append-paths", so commit hooks '. 474 '(which execute with an empty "PATH") will not be able to '. 475 'find "svnlook". Add `%s` to %s.', 476 $path, 477 $this->getEnvConfigLink()))); 478 } 479 } 480 } 481 } 482 483 $doc_href = PhabricatorEnv::getDoclink('Managing Daemons with phd'); 484 485 $daemon_instructions = pht( 486 'Use %s to start daemons. See %s.', 487 phutil_tag('tt', array(), 'bin/phd start'), 488 phutil_tag( 489 'a', 490 array( 491 'href' => $doc_href, 492 ), 493 pht('Managing Daemons with phd'))); 494 495 496 $pull_daemon = id(new PhabricatorDaemonLogQuery()) 497 ->setViewer(PhabricatorUser::getOmnipotentUser()) 498 ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) 499 ->withDaemonClasses(array('PhabricatorRepositoryPullLocalDaemon')) 500 ->setLimit(1) 501 ->execute(); 502 503 if ($pull_daemon) { 504 505 // TODO: In a cluster environment, we need a daemon on this repository's 506 // host, specifically, and we aren't checking for that right now. This 507 // is a reasonable proxy for things being more-or-less correctly set up, 508 // though. 509 510 $view->addItem( 511 id(new PHUIStatusItemView()) 512 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 513 ->setTarget(pht('Pull Daemon Running'))); 514 } else { 515 $view->addItem( 516 id(new PHUIStatusItemView()) 517 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 518 ->setTarget(pht('Pull Daemon Not Running')) 519 ->setNote($daemon_instructions)); 520 } 521 522 523 $task_daemon = id(new PhabricatorDaemonLogQuery()) 524 ->setViewer(PhabricatorUser::getOmnipotentUser()) 525 ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) 526 ->withDaemonClasses(array('PhabricatorTaskmasterDaemon')) 527 ->setLimit(1) 528 ->execute(); 529 if ($task_daemon) { 530 $view->addItem( 531 id(new PHUIStatusItemView()) 532 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 533 ->setTarget(pht('Task Daemon Running'))); 534 } else { 535 $view->addItem( 536 id(new PHUIStatusItemView()) 537 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 538 ->setTarget(pht('Task Daemon Not Running')) 539 ->setNote($daemon_instructions)); 540 } 541 542 543 if ($is_cluster) { 544 // Just omit this status check for now in cluster environments. We 545 // could make a service call and pull it from the repository host 546 // eventually. 547 } else if ($repository->usesLocalWorkingCopy()) { 548 $local_parent = dirname($repository->getLocalPath()); 549 if (Filesystem::pathExists($local_parent)) { 550 $view->addItem( 551 id(new PHUIStatusItemView()) 552 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 553 ->setTarget(pht('Storage Directory OK')) 554 ->setNote(phutil_tag('tt', array(), $local_parent))); 555 } else { 556 $view->addItem( 557 id(new PHUIStatusItemView()) 558 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 559 ->setTarget(pht('No Storage Directory')) 560 ->setNote( 561 pht( 562 'Storage directory %s does not exist, or is not readable by '. 563 'the webserver. Create this directory or make it readable.', 564 phutil_tag('tt', array(), $local_parent)))); 565 return $view; 566 } 567 568 $local_path = $repository->getLocalPath(); 569 $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_INIT); 570 if ($message) { 571 switch ($message->getStatusCode()) { 572 case PhabricatorRepositoryStatusMessage::CODE_ERROR: 573 $view->addItem( 574 id(new PHUIStatusItemView()) 575 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 576 ->setTarget(pht('Initialization Error')) 577 ->setNote($message->getParameter('message'))); 578 return $view; 579 case PhabricatorRepositoryStatusMessage::CODE_OKAY: 580 if (Filesystem::pathExists($local_path)) { 581 $view->addItem( 582 id(new PHUIStatusItemView()) 583 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 584 ->setTarget(pht('Working Copy OK')) 585 ->setNote(phutil_tag('tt', array(), $local_path))); 586 } else { 587 $view->addItem( 588 id(new PHUIStatusItemView()) 589 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 590 ->setTarget(pht('Working Copy Error')) 591 ->setNote( 592 pht( 593 'Working copy %s has been deleted, or is not '. 594 'readable by the webserver. Make this directory '. 595 'readable. If it has been deleted, the daemons should '. 596 'restore it automatically.', 597 phutil_tag('tt', array(), $local_path)))); 598 return $view; 599 } 600 break; 601 default: 602 $view->addItem( 603 id(new PHUIStatusItemView()) 604 ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green') 605 ->setTarget(pht('Initializing Working Copy')) 606 ->setNote(pht('Daemons are initializing the working copy.'))); 607 return $view; 608 } 609 } else { 610 $view->addItem( 611 id(new PHUIStatusItemView()) 612 ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange') 613 ->setTarget(pht('No Working Copy Yet')) 614 ->setNote( 615 pht('Waiting for daemons to build a working copy.'))); 616 return $view; 617 } 618 } 619 620 $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH); 621 if ($message) { 622 switch ($message->getStatusCode()) { 623 case PhabricatorRepositoryStatusMessage::CODE_ERROR: 624 $message = $message->getParameter('message'); 625 626 $suggestion = null; 627 if (preg_match('/Permission denied \(publickey\)./', $message)) { 628 $suggestion = pht( 629 'Public Key Error: This error usually indicates that the '. 630 'keypair you have configured does not have permission to '. 631 'access the repository.'); 632 } 633 634 $view->addItem( 635 id(new PHUIStatusItemView()) 636 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red') 637 ->setTarget(pht('Update Error')) 638 ->setNote($suggestion)); 639 return $view; 640 case PhabricatorRepositoryStatusMessage::CODE_OKAY: 641 $ago = (PhabricatorTime::getNow() - $message->getEpoch()); 642 $view->addItem( 643 id(new PHUIStatusItemView()) 644 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 645 ->setTarget(pht('Updates OK')) 646 ->setNote( 647 pht( 648 'Last updated %s (%s ago).', 649 phabricator_datetime($message->getEpoch(), $viewer), 650 phutil_format_relative_time_detailed($ago)))); 651 break; 652 } 653 } else { 654 $view->addItem( 655 id(new PHUIStatusItemView()) 656 ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange') 657 ->setTarget(pht('Waiting For Update')) 658 ->setNote( 659 pht('Waiting for daemons to read updates.'))); 660 } 661 662 if ($repository->isImporting()) { 663 $ratio = $repository->loadImportProgress(); 664 $percentage = sprintf('%.2f%%', 100 * $ratio); 665 666 $view->addItem( 667 id(new PHUIStatusItemView()) 668 ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green') 669 ->setTarget(pht('Importing')) 670 ->setNote( 671 pht('%s Complete', $percentage))); 672 } else { 673 $view->addItem( 674 id(new PHUIStatusItemView()) 675 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green') 676 ->setTarget(pht('Fully Imported'))); 677 } 678 679 if (idx($messages, PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE)) { 680 $view->addItem( 681 id(new PHUIStatusItemView()) 682 ->setIcon(PHUIStatusItemView::ICON_UP, 'indigo') 683 ->setTarget(pht('Prioritized')) 684 ->setNote(pht('This repository will be updated soon!'))); 685 } 686 687 return $view; 688 } 689 690 private function buildRepositoryRawError( 691 PhabricatorRepository $repository, 692 array $messages) { 693 $viewer = $this->getViewer(); 694 695 $can_edit = PhabricatorPolicyFilter::hasCapability( 696 $viewer, 697 $repository, 698 PhabricatorPolicyCapability::CAN_EDIT); 699 700 $raw_error = null; 701 702 $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH); 703 if ($message) { 704 switch ($message->getStatusCode()) { 705 case PhabricatorRepositoryStatusMessage::CODE_ERROR: 706 $raw_error = $message->getParameter('message'); 707 break; 708 } 709 } 710 711 if ($raw_error !== null) { 712 if (!$can_edit) { 713 $raw_message = pht( 714 'You must be able to edit a repository to see raw error messages '. 715 'because they sometimes disclose sensitive information.'); 716 $raw_message = phutil_tag('em', array(), $raw_message); 717 } else { 718 $raw_message = phutil_escape_html_newlines($raw_error); 719 } 720 } else { 721 $raw_message = null; 722 } 723 724 return $raw_message; 725 } 726 727 private function loadStatusMessages(PhabricatorRepository $repository) { 728 $messages = id(new PhabricatorRepositoryStatusMessage()) 729 ->loadAllWhere('repositoryID = %d', $repository->getID()); 730 $messages = mpull($messages, null, 'getStatusType'); 731 732 return $messages; 733 } 734 735 private function getEnvConfigLink() { 736 $config_href = '/config/edit/environment.append-paths/'; 737 return phutil_tag( 738 'a', 739 array( 740 'href' => $config_href, 741 ), 742 'environment.append-paths'); 743 } 744 745 private function buildStateView(PhabricatorRepository $repository) { 746 $viewer = $this->getViewer(); 747 $is_new = $repository->isNewlyInitialized(); 748 749 $view = id(new PHUIPropertyListView()) 750 ->setViewer($viewer); 751 752 if (!$repository->isTracked()) { 753 if ($is_new) { 754 $active_icon = 'fa-ban'; 755 $active_color = 'yellow'; 756 $active_label = pht('Not Activated Yet'); 757 $active_note = pht('Complete Setup and Activate Repository'); 758 } else { 759 $active_icon = 'fa-times'; 760 $active_color = 'red'; 761 $active_label = pht('Not Active'); 762 $active_note = pht('Repository Disabled'); 763 } 764 } else if ($repository->isImporting()) { 765 $active_icon = 'fa-hourglass'; 766 $active_color = 'yellow'; 767 $active_label = pht('Importing...'); 768 $active_note = null; 769 } else { 770 $active_icon = 'fa-check'; 771 $active_color = 'green'; 772 $active_label = pht('Repository Active'); 773 $active_note = null; 774 } 775 776 $active_view = id(new PHUIStatusListView()) 777 ->addItem( 778 id(new PHUIStatusItemView()) 779 ->setIcon($active_icon, $active_color) 780 ->setTarget($active_label) 781 ->setNote($active_note)); 782 783 if ($repository->isPublishingDisabled()) { 784 $publishing_icon = 'fa-times'; 785 $publishing_color = 'red'; 786 $publishing_label = pht('Not Publishing'); 787 $publishing_note = pht('Publishing Disabled'); 788 } else if (!$repository->isTracked()) { 789 $publishing_icon = 'fa-ban'; 790 $publishing_color = 'yellow'; 791 $publishing_label = pht('Not Publishing'); 792 if ($is_new) { 793 $publishing_note = pht('Repository Not Active Yet'); 794 } else { 795 $publishing_note = pht('Repository Inactive'); 796 } 797 } else if ($repository->isImporting()) { 798 $publishing_icon = 'fa-ban'; 799 $publishing_color = 'yellow'; 800 $publishing_label = pht('Not Publishing'); 801 $publishing_note = pht('Repository Importing'); 802 } else { 803 $publishing_icon = 'fa-check'; 804 $publishing_color = 'green'; 805 $publishing_label = pht('Publishing Active'); 806 $publishing_note = null; 807 } 808 809 $publishing_view = id(new PHUIStatusListView()) 810 ->addItem( 811 id(new PHUIStatusItemView()) 812 ->setIcon($publishing_icon, $publishing_color) 813 ->setTarget($publishing_label) 814 ->setNote($publishing_note)); 815 816 $view->addProperty(pht('Active'), $active_view); 817 $view->addProperty(pht('Publishing'), $publishing_view); 818 819 return $this->newBox(pht('State'), $view); 820 } 821 822}