@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
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Move "Remote URI" to modern repository editor thing

Summary:
Ref T2231. Allows you to edit the remote URI and credentials.

This is a little bit funky because I'm reusing some of the pages on the new (not-yet-hooked-up) create form. Specifically, it had pages like this:

- Repo Type
- Name/Callsign/Remote
- Auth
- Done

I split "Name/Callsign/Remote" into "Name/Callsign" and "Remote", then when editing the remote I just take you through "Remote" and "Auth" and then back. This lets us reuse the giant pile of protocol/URI sanity checking logic and ends up being pretty clean, although it's a little weird that the "Create" controller does both full-create and edit-remote.

Test Plan: See screenshots.

Reviewers: btrahan, chad

Reviewed By: btrahan

CC: chad, aran

Maniphest Tasks: T2231

Differential Revision: https://secure.phabricator.com/D7405

+432 -113
+47 -47
src/__celerity_resource_map__.php
··· 3858 3858 ), 3859 3859 'phui-form-view-css' => 3860 3860 array( 3861 - 'uri' => '/res/157ddd8b/rsrc/css/phui/phui-form-view.css', 3861 + 'uri' => '/res/3621b05d/rsrc/css/phui/phui-form-view.css', 3862 3862 'type' => 'css', 3863 3863 'requires' => 3864 3864 array( ··· 3885 3885 ), 3886 3886 'phui-info-panel-css' => 3887 3887 array( 3888 - 'uri' => '/res/0a9c55c3/rsrc/css/phui/phui-info-panel.css', 3888 + 'uri' => '/res/e0ba8d04/rsrc/css/phui/phui-info-panel.css', 3889 3889 'type' => 'css', 3890 3890 'requires' => 3891 3891 array( ··· 4318 4318 ), array( 4319 4319 'packages' => 4320 4320 array( 4321 - '8486b05c' => 4321 + '3b488eea' => 4322 4322 array( 4323 4323 'name' => 'core.pkg.css', 4324 4324 'symbols' => ··· 4367 4367 41 => 'phabricator-tag-view-css', 4368 4368 42 => 'phui-list-view-css', 4369 4369 ), 4370 - 'uri' => '/res/pkg/8486b05c/core.pkg.css', 4370 + 'uri' => '/res/pkg/3b488eea/core.pkg.css', 4371 4371 'type' => 'css', 4372 4372 ), 4373 4373 '2c1dba03' => ··· 4559 4559 ), 4560 4560 'reverse' => 4561 4561 array( 4562 - 'aphront-dialog-view-css' => '8486b05c', 4563 - 'aphront-error-view-css' => '8486b05c', 4564 - 'aphront-list-filter-view-css' => '8486b05c', 4565 - 'aphront-pager-view-css' => '8486b05c', 4566 - 'aphront-panel-view-css' => '8486b05c', 4567 - 'aphront-table-view-css' => '8486b05c', 4568 - 'aphront-tokenizer-control-css' => '8486b05c', 4569 - 'aphront-tooltip-css' => '8486b05c', 4570 - 'aphront-typeahead-control-css' => '8486b05c', 4562 + 'aphront-dialog-view-css' => '3b488eea', 4563 + 'aphront-error-view-css' => '3b488eea', 4564 + 'aphront-list-filter-view-css' => '3b488eea', 4565 + 'aphront-pager-view-css' => '3b488eea', 4566 + 'aphront-panel-view-css' => '3b488eea', 4567 + 'aphront-table-view-css' => '3b488eea', 4568 + 'aphront-tokenizer-control-css' => '3b488eea', 4569 + 'aphront-tooltip-css' => '3b488eea', 4570 + 'aphront-typeahead-control-css' => '3b488eea', 4571 4571 'differential-changeset-view-css' => 'f87db3d0', 4572 4572 'differential-core-view-css' => 'f87db3d0', 4573 4573 'differential-inline-comment-editor' => '5e9e5c4e', ··· 4581 4581 'differential-table-of-contents-css' => 'f87db3d0', 4582 4582 'diffusion-commit-view-css' => '270f4eb4', 4583 4583 'diffusion-icons-css' => '270f4eb4', 4584 - 'global-drag-and-drop-css' => '8486b05c', 4584 + 'global-drag-and-drop-css' => '3b488eea', 4585 4585 'inline-comment-summary-css' => 'f87db3d0', 4586 4586 'javelin-aphlict' => '2c1dba03', 4587 4587 'javelin-behavior' => '3e3be199', ··· 4656 4656 'javelin-util' => '3e3be199', 4657 4657 'javelin-vector' => '3e3be199', 4658 4658 'javelin-workflow' => '3e3be199', 4659 - 'lightbox-attachment-css' => '8486b05c', 4659 + 'lightbox-attachment-css' => '3b488eea', 4660 4660 'maniphest-task-summary-css' => '49898640', 4661 - 'phabricator-action-list-view-css' => '8486b05c', 4662 - 'phabricator-application-launch-view-css' => '8486b05c', 4661 + 'phabricator-action-list-view-css' => '3b488eea', 4662 + 'phabricator-application-launch-view-css' => '3b488eea', 4663 4663 'phabricator-busy' => '2c1dba03', 4664 4664 'phabricator-content-source-view-css' => 'f87db3d0', 4665 - 'phabricator-core-css' => '8486b05c', 4666 - 'phabricator-crumbs-view-css' => '8486b05c', 4665 + 'phabricator-core-css' => '3b488eea', 4666 + 'phabricator-crumbs-view-css' => '3b488eea', 4667 4667 'phabricator-drag-and-drop-file-upload' => '5e9e5c4e', 4668 4668 'phabricator-dropdown-menu' => '2c1dba03', 4669 4669 'phabricator-file-upload' => '2c1dba03', 4670 - 'phabricator-filetree-view-css' => '8486b05c', 4671 - 'phabricator-flag-css' => '8486b05c', 4670 + 'phabricator-filetree-view-css' => '3b488eea', 4671 + 'phabricator-flag-css' => '3b488eea', 4672 4672 'phabricator-hovercard' => '2c1dba03', 4673 - 'phabricator-jump-nav' => '8486b05c', 4673 + 'phabricator-jump-nav' => '3b488eea', 4674 4674 'phabricator-keyboard-shortcut' => '2c1dba03', 4675 4675 'phabricator-keyboard-shortcut-manager' => '2c1dba03', 4676 - 'phabricator-main-menu-view' => '8486b05c', 4676 + 'phabricator-main-menu-view' => '3b488eea', 4677 4677 'phabricator-menu-item' => '2c1dba03', 4678 - 'phabricator-nav-view-css' => '8486b05c', 4678 + 'phabricator-nav-view-css' => '3b488eea', 4679 4679 'phabricator-notification' => '2c1dba03', 4680 - 'phabricator-notification-css' => '8486b05c', 4681 - 'phabricator-notification-menu-css' => '8486b05c', 4680 + 'phabricator-notification-css' => '3b488eea', 4681 + 'phabricator-notification-menu-css' => '3b488eea', 4682 4682 'phabricator-object-selector-css' => 'f87db3d0', 4683 4683 'phabricator-phtize' => '2c1dba03', 4684 4684 'phabricator-prefab' => '2c1dba03', 4685 4685 'phabricator-project-tag-css' => '49898640', 4686 - 'phabricator-remarkup-css' => '8486b05c', 4686 + 'phabricator-remarkup-css' => '3b488eea', 4687 4687 'phabricator-shaped-request' => '5e9e5c4e', 4688 - 'phabricator-side-menu-view-css' => '8486b05c', 4689 - 'phabricator-standard-page-view' => '8486b05c', 4690 - 'phabricator-tag-view-css' => '8486b05c', 4688 + 'phabricator-side-menu-view-css' => '3b488eea', 4689 + 'phabricator-standard-page-view' => '3b488eea', 4690 + 'phabricator-tag-view-css' => '3b488eea', 4691 4691 'phabricator-textareautils' => '2c1dba03', 4692 4692 'phabricator-tooltip' => '2c1dba03', 4693 - 'phabricator-transaction-view-css' => '8486b05c', 4694 - 'phabricator-zindex-css' => '8486b05c', 4695 - 'phui-button-css' => '8486b05c', 4696 - 'phui-form-css' => '8486b05c', 4697 - 'phui-form-view-css' => '8486b05c', 4698 - 'phui-header-view-css' => '8486b05c', 4699 - 'phui-icon-view-css' => '8486b05c', 4700 - 'phui-list-view-css' => '8486b05c', 4701 - 'phui-object-item-list-view-css' => '8486b05c', 4702 - 'phui-property-list-view-css' => '8486b05c', 4703 - 'phui-spacing-css' => '8486b05c', 4704 - 'sprite-apps-large-css' => '8486b05c', 4705 - 'sprite-gradient-css' => '8486b05c', 4706 - 'sprite-icons-css' => '8486b05c', 4707 - 'sprite-menu-css' => '8486b05c', 4708 - 'sprite-status-css' => '8486b05c', 4709 - 'syntax-highlighting-css' => '8486b05c', 4693 + 'phabricator-transaction-view-css' => '3b488eea', 4694 + 'phabricator-zindex-css' => '3b488eea', 4695 + 'phui-button-css' => '3b488eea', 4696 + 'phui-form-css' => '3b488eea', 4697 + 'phui-form-view-css' => '3b488eea', 4698 + 'phui-header-view-css' => '3b488eea', 4699 + 'phui-icon-view-css' => '3b488eea', 4700 + 'phui-list-view-css' => '3b488eea', 4701 + 'phui-object-item-list-view-css' => '3b488eea', 4702 + 'phui-property-list-view-css' => '3b488eea', 4703 + 'phui-spacing-css' => '3b488eea', 4704 + 'sprite-apps-large-css' => '3b488eea', 4705 + 'sprite-gradient-css' => '3b488eea', 4706 + 'sprite-icons-css' => '3b488eea', 4707 + 'sprite-menu-css' => '3b488eea', 4708 + 'sprite-status-css' => '3b488eea', 4709 + 'syntax-highlighting-css' => '3b488eea', 4710 4710 ), 4711 4711 ));
+1
src/applications/diffusion/application/PhabricatorApplicationDiffusion.php
··· 72 72 'branches/' => 'DiffusionRepositoryEditBranchesController', 73 73 'subversion/' => 'DiffusionRepositoryEditSubversionController', 74 74 'actions/' => 'DiffusionRepositoryEditActionsController', 75 + '(?P<edit>remote)/' => 'DiffusionRepositoryCreateController', 75 76 ), 76 77 ), 77 78 'inline/' => array(
+207 -58
src/applications/diffusion/controller/DiffusionRepositoryCreateController.php
··· 2 2 3 3 final class DiffusionRepositoryCreateController extends DiffusionController { 4 4 5 + private $edit; 6 + private $repository; 7 + 8 + public function willProcessRequest(array $data) { 9 + parent::willProcessRequest($data); 10 + $this->edit = idx($data, 'edit'); 11 + } 12 + 5 13 public function processRequest() { 6 14 $request = $this->getRequest(); 7 15 $viewer = $request->getUser(); 8 16 17 + // NOTE: We can end up here via either "Create Repository" or via 18 + // "Edit Remote". In the latter case, we show only a few of the pages. 19 + 20 + $repository = null; 21 + if ($this->edit) { 22 + $repository = $this->getDiffusionRequest()->getRepository(); 23 + 24 + // Make sure we have CAN_EDIT. 25 + id(new PhabricatorRepositoryQuery()) 26 + ->setViewer($viewer) 27 + ->withIDs(array($repository->getID())) 28 + ->requireCapabilities( 29 + array( 30 + PhabricatorPolicyCapability::CAN_VIEW, 31 + PhabricatorPolicyCapability::CAN_EDIT, 32 + )) 33 + ->executeOne(); 34 + 35 + $this->setRepository($repository); 36 + 37 + $cancel_uri = $this->getRepositoryControllerURI($repository, 'edit/'); 38 + } else { 39 + $cancel_uri = $this->getApplicationURI(); 40 + } 41 + 9 42 $form = id(new PHUIPagedFormView()) 10 43 ->setUser($viewer) 11 - ->addPage('vcs', $this->buildVCSPage()) 12 - ->addPage('name', $this->buildNamePage()) 13 - ->addPage('auth', $this->buildAuthPage()) 14 - ->addPage('done', $this->buildDonePage()); 44 + ->setCancelURI($cancel_uri); 45 + 46 + switch ($this->edit) { 47 + case 'remote': 48 + $title = pht('Edit Remote'); 49 + $form 50 + ->addPage('remote-uri', $this->buildRemoteURIPage()) 51 + ->addPage('auth', $this->buildAuthPage()); 52 + break; 53 + default: 54 + $title = pht('Import Repository'); 55 + $form 56 + ->addPage('vcs', $this->buildVCSPage()) 57 + ->addPage('name', $this->buildNamePage()) 58 + ->addPage('remote-uri', $this->buildRemoteURIPage()) 59 + ->addPage('auth', $this->buildAuthPage()) 60 + ->addPage('done', $this->buildDonePage()); 61 + break; 62 + } 15 63 16 64 if ($request->isFormPost()) { 17 65 $form->readFromRequest($request); 18 66 if ($form->isComplete()) { 19 - // TODO: This exception is heartwarming but should probably take more 20 - // substantive actions. 21 - throw new Exception("GOOD JOB AT FORM"); 67 + 68 + if ($this->edit != 'remote') { 69 + // TODO: This exception is heartwarming but should probably take more 70 + // substantive actions. 71 + throw new Exception("GOOD JOB AT FORM"); 72 + } 73 + 74 + $template = id(new PhabricatorRepositoryTransaction()); 75 + 76 + $type_remote_uri = PhabricatorRepositoryTransaction::TYPE_REMOTE_URI; 77 + $type_ssh_login = PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN; 78 + $type_ssh_key = PhabricatorRepositoryTransaction::TYPE_SSH_KEY; 79 + $type_ssh_keyfile = PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE; 80 + $type_http_login = PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN; 81 + $type_http_pass = PhabricatorRepositoryTransaction::TYPE_HTTP_PASS; 82 + 83 + $xactions = array(); 84 + 85 + $xactions[] = id(clone $template) 86 + ->setTransactionType($type_remote_uri) 87 + ->setNewValue( 88 + $form->getPage('remote-uri')->getControl('remoteURI')->getValue()); 89 + 90 + $xactions[] = id(clone $template) 91 + ->setTransactionType($type_ssh_login) 92 + ->setNewValue( 93 + $form->getPage('auth')->getControl('ssh-login')->getValue()); 94 + 95 + $xactions[] = id(clone $template) 96 + ->setTransactionType($type_ssh_key) 97 + ->setNewValue( 98 + $form->getPage('auth')->getControl('ssh-key')->getValue()); 99 + 100 + $xactions[] = id(clone $template) 101 + ->setTransactionType($type_ssh_keyfile) 102 + ->setNewValue( 103 + $form->getPage('auth')->getControl('ssh-keyfile')->getValue()); 104 + 105 + $xactions[] = id(clone $template) 106 + ->setTransactionType($type_http_login) 107 + ->setNewValue( 108 + $form->getPage('auth')->getControl('http-login')->getValue()); 109 + 110 + $xactions[] = id(clone $template) 111 + ->setTransactionType($type_http_pass) 112 + ->setNewValue( 113 + $form->getPage('auth')->getControl('http-pass')->getValue()); 114 + 115 + id(new PhabricatorRepositoryEditor()) 116 + ->setContinueOnNoEffect(true) 117 + ->setContentSourceFromRequest($request) 118 + ->setActor($viewer) 119 + ->applyTransactions($repository, $xactions); 120 + 121 + $repo_uri = $this->getRepositoryControllerURI($repository, 'edit/'); 122 + return id(new AphrontRedirectResponse())->setURI($repo_uri); 22 123 } 23 124 } else { 24 - $form->readFromObject(null); 125 + $dict = array(); 126 + if ($repository) { 127 + $dict = array( 128 + 'remoteURI' => $repository->getRemoteURI(), 129 + 'ssh-login' => $repository->getDetail('ssh-login'), 130 + 'ssh-key' => $repository->getDetail('ssh-key'), 131 + 'ssh-keyfile' => $repository->getDetail('ssh-keyfile'), 132 + 'http-login' => $repository->getDetail('http-login'), 133 + 'http-pass' => $repository->getDetail('http-pass'), 134 + ); 135 + } 136 + $form->readFromObject($dict); 25 137 } 26 - 27 - $title = pht('Import Repository'); 28 138 29 139 $crumbs = $this->buildCrumbs(); 30 140 $crumbs->addCrumb( ··· 120 230 ->setUser($this->getRequest()->getUser()) 121 231 ->setPageName(pht('Repository Name and Location')) 122 232 ->setValidateFormPageCallback(array($this, 'validateNamePage')) 123 - ->setAdjustFormPageCallback(array($this, 'adjustNamePage')) 124 233 ->addRemarkupInstructions( 125 234 pht( 126 235 '**Choose a human-readable name for this repository**, like '. ··· 145 254 id(new AphrontFormTextControl()) 146 255 ->setName('callsign') 147 256 ->setLabel(pht('Callsign')) 148 - ->setCaption(pht('Short UPPERCASE identifier.'))) 257 + ->setCaption(pht('Short UPPERCASE identifier.'))); 258 + } 259 + 260 + public function validateNamePage(PHUIFormPageView $page) { 261 + $c_name = $page->getControl('name'); 262 + $v_name = $c_name->getValue(); 263 + if (!strlen($v_name)) { 264 + $c_name->setError(pht('Required')); 265 + $page->addPageError( 266 + pht('You must choose a name for this repository.')); 267 + } 268 + 269 + $c_call = $page->getControl('callsign'); 270 + $v_call = $c_call->getValue(); 271 + if (!strlen($v_call)) { 272 + $c_call->setError(pht('Required')); 273 + $page->addPageError( 274 + pht('You must choose a callsign for this repository.')); 275 + } else if (!preg_match('/^[A-Z]+$/', $v_call)) { 276 + $c_call->setError(pht('Invalid')); 277 + $page->addPageError( 278 + pht('The callsign must contain only UPPERCASE letters.')); 279 + } else { 280 + $exists = false; 281 + try { 282 + $repo = id(new PhabricatorRepositoryQuery()) 283 + ->setViewer($this->getRequest()->getUser()) 284 + ->withCallsigns(array($v_call)) 285 + ->executeOne(); 286 + $exists = (bool)$repo; 287 + } catch (PhabricatorPolicyException $ex) { 288 + $exists = true; 289 + } 290 + if ($exists) { 291 + $c_call->setError(pht('Not Unique')); 292 + $page->addPageError( 293 + pht( 294 + 'Another repository already uses that callsign. You must choose '. 295 + 'a unique callsign.')); 296 + } 297 + } 298 + 299 + return $c_name->isValid() && 300 + $c_call->isValid(); 301 + } 302 + 303 + 304 + /* -( Page: Remote URI )--------------------------------------------------- */ 305 + 306 + 307 + private function buildRemoteURIPage() { 308 + return id(new PHUIFormPageView()) 309 + ->setUser($this->getRequest()->getUser()) 310 + ->setPageName(pht('Repository Remote URI')) 311 + ->setValidateFormPageCallback(array($this, 'validateRemoteURIPage')) 312 + ->setAdjustFormPageCallback(array($this, 'adjustRemoteURIPage')) 149 313 ->addControl( 150 314 id(new AphrontFormTextControl()) 151 315 ->setName('remoteURI')); 152 316 } 153 317 154 - public function adjustNamePage(PHUIFormPageView $page) { 318 + public function adjustRemoteURIPage(PHUIFormPageView $page) { 155 319 $form = $page->getForm(); 156 320 157 321 $is_git = false; 158 322 $is_svn = false; 159 323 $is_mercurial = false; 160 324 161 - switch ($form->getPage('vcs')->getControl('vcs')->getValue()) { 325 + if ($this->getRepository()) { 326 + $vcs = $this->getRepository()->getVersionControlSystem(); 327 + } else { 328 + $vcs = $form->getPage('vcs')->getControl('vcs')->getValue(); 329 + } 330 + 331 + switch ($vcs) { 162 332 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 163 333 $is_git = true; 164 334 break; ··· 220 390 $page->getControl('remoteURI')->setLabel($uri_label); 221 391 } 222 392 223 - public function validateNamePage(PHUIFormPageView $page) { 224 - $c_name = $page->getControl('name'); 225 - $v_name = $c_name->getValue(); 226 - if (!strlen($v_name)) { 227 - $c_name->setError(pht('Required')); 228 - $page->addPageError( 229 - pht('You must choose a name for this repository.')); 230 - } 231 - 232 - $c_call = $page->getControl('callsign'); 233 - $v_call = $c_call->getValue(); 234 - if (!strlen($v_call)) { 235 - $c_call->setError(pht('Required')); 236 - $page->addPageError( 237 - pht('You must choose a callsign for this repository.')); 238 - } else if (!preg_match('/^[A-Z]+$/', $v_call)) { 239 - $c_call->setError(pht('Invalid')); 240 - $page->addPageError( 241 - pht('The callsign must contain only UPPERCASE letters.')); 242 - } else { 243 - $exists = false; 244 - try { 245 - $repo = id(new PhabricatorRepositoryQuery()) 246 - ->setViewer($this->getRequest()->getUser()) 247 - ->withCallsigns(array($v_call)) 248 - ->executeOne(); 249 - $exists = (bool)$repo; 250 - } catch (PhabricatorPolicyException $ex) { 251 - $exists = true; 252 - } 253 - if ($exists) { 254 - $c_call->setError(pht('Not Unique')); 255 - $page->addPageError( 256 - pht( 257 - 'Another repository already uses that callsign. You must choose '. 258 - 'a unique callsign.')); 259 - } 260 - } 261 - 393 + public function validateRemoteURIPage(PHUIFormPageView $page) { 262 394 $c_remote = $page->getControl('remoteURI'); 263 395 $v_remote = $c_remote->getValue(); 264 396 ··· 301 433 } 302 434 } 303 435 304 - return $c_name->isValid() && 305 - $c_call->isValid() && 306 - $c_remote->isValid(); 436 + return $c_remote->isValid(); 307 437 } 308 438 309 439 ··· 346 476 347 477 public function adjustAuthPage($page) { 348 478 $form = $page->getForm(); 349 - $remote_uri = $form->getPage('name')->getControl('remoteURI')->getValue(); 350 - $vcs = $form->getPage('vcs')->getControl('vcs')->getValue(); 479 + 480 + $remote_uri = $form->getPage('remote-uri') 481 + ->getControl('remoteURI') 482 + ->getValue(); 483 + 484 + if ($this->getRepository()) { 485 + $vcs = $this->getRepository()->getVersionControlSystem(); 486 + } else { 487 + $vcs = $form->getPage('vcs')->getControl('vcs')->getValue(); 488 + } 489 + 351 490 $proto = $this->getRemoteURIProtocol($remote_uri); 352 491 $remote_user = $this->getRemoteURIUser($remote_uri); 353 492 ··· 540 679 private function isUsernamePasswordProtocol($proto) { 541 680 return ($proto == 'http' || $proto == 'https' || $proto == 'svn'); 542 681 } 682 + 683 + private function setRepository(PhabricatorRepository $repository) { 684 + $this->repository = $repository; 685 + return $this; 686 + } 687 + 688 + private function getRepository() { 689 + return $this->repository; 690 + } 691 + 543 692 544 693 }
+47
src/applications/diffusion/controller/DiffusionRepositoryEditController.php
··· 50 50 $policy_properties = 51 51 $this->buildPolicyProperties($repository, $policy_actions); 52 52 53 + $remote_properties = $this->buildRemoteProperties( 54 + $repository, 55 + $this->buildRemoteActions($repository)); 56 + 53 57 $encoding_actions = $this->buildEncodingActions($repository); 54 58 $encoding_properties = 55 59 $this->buildEncodingProperties($repository, $encoding_actions); ··· 98 102 ->setHeader($header) 99 103 ->addPropertyList($basic_properties) 100 104 ->addPropertyList($policy_properties) 105 + ->addPropertyList($remote_properties) 101 106 ->addPropertyList($encoding_properties); 102 107 103 108 if ($branches_properties) { ··· 441 446 : pht('On'); 442 447 $autoclose = phutil_tag('em', array(), $autoclose); 443 448 $view->addProperty(pht('Autoclose'), $autoclose); 449 + 450 + return $view; 451 + } 452 + 453 + private function buildRemoteActions(PhabricatorRepository $repository) { 454 + $viewer = $this->getRequest()->getUser(); 455 + 456 + $view = id(new PhabricatorActionListView()) 457 + ->setObjectURI($this->getRequest()->getRequestURI()) 458 + ->setUser($viewer); 459 + 460 + $can_edit = PhabricatorPolicyFilter::hasCapability( 461 + $viewer, 462 + $repository, 463 + PhabricatorPolicyCapability::CAN_EDIT); 464 + 465 + $edit = id(new PhabricatorActionView()) 466 + ->setIcon('edit') 467 + ->setName(pht('Edit Remote')) 468 + ->setHref( 469 + $this->getRepositoryControllerURI($repository, 'edit/remote/')) 470 + ->setWorkflow(!$can_edit) 471 + ->setDisabled(!$can_edit); 472 + $view->addAction($edit); 473 + 474 + return $view; 475 + } 476 + 477 + private function buildRemoteProperties( 478 + PhabricatorRepository $repository, 479 + PhabricatorActionListView $actions) { 480 + 481 + $viewer = $this->getRequest()->getUser(); 482 + 483 + $view = id(new PHUIPropertyListView()) 484 + ->setUser($viewer) 485 + ->setActionList($actions) 486 + ->addSectionHeader(pht('Remote')); 487 + 488 + $view->addProperty( 489 + pht('Remote URI'), 490 + $repository->getDetail('remote-uri')); 444 491 445 492 return $view; 446 493 }
+43
src/applications/repository/editor/PhabricatorRepositoryEditor.php
··· 17 17 $types[] = PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH; 18 18 $types[] = PhabricatorRepositoryTransaction::TYPE_NOTIFY; 19 19 $types[] = PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE; 20 + $types[] = PhabricatorRepositoryTransaction::TYPE_REMOTE_URI; 21 + $types[] = PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN; 22 + $types[] = PhabricatorRepositoryTransaction::TYPE_SSH_KEY; 23 + $types[] = PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE; 24 + $types[] = PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN; 25 + $types[] = PhabricatorRepositoryTransaction::TYPE_HTTP_PASS; 26 + 20 27 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 21 28 $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; 22 29 ··· 50 57 return (int)!$object->getDetail('herald-disabled'); 51 58 case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE: 52 59 return (int)!$object->getDetail('disable-autoclose'); 60 + case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI: 61 + return $object->getDetail('remote-uri'); 62 + case PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN: 63 + return $object->getDetail('ssh-login'); 64 + case PhabricatorRepositoryTransaction::TYPE_SSH_KEY: 65 + return $object->getDetail('ssh-key'); 66 + case PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE: 67 + return $object->getDetail('ssh-keyfile'); 68 + case PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN: 69 + return $object->getDetail('http-login'); 70 + case PhabricatorRepositoryTransaction::TYPE_HTTP_PASS: 71 + return $object->getDetail('http-pass'); 53 72 } 54 73 } 55 74 ··· 67 86 case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY: 68 87 case PhabricatorRepositoryTransaction::TYPE_UUID: 69 88 case PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH: 89 + case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI: 90 + case PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN: 91 + case PhabricatorRepositoryTransaction::TYPE_SSH_KEY: 92 + case PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE: 93 + case PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN: 94 + case PhabricatorRepositoryTransaction::TYPE_HTTP_PASS: 70 95 return $xaction->getNewValue(); 71 96 case PhabricatorRepositoryTransaction::TYPE_NOTIFY: 72 97 case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE: ··· 112 137 break; 113 138 case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE: 114 139 $object->setDetail('disable-autoclose', (int)!$xaction->getNewValue()); 140 + break; 141 + case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI: 142 + $object->setDetail('remote-uri', $xaction->getNewValue()); 143 + break; 144 + case PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN: 145 + $object->setDetail('ssh-login', $xaction->getNewValue()); 146 + break; 147 + case PhabricatorRepositoryTransaction::TYPE_SSH_KEY: 148 + $object->setDetail('ssh-key', $xaction->getNewValue()); 149 + break; 150 + case PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE: 151 + $object->setDetail('ssh-keyfile', $xaction->getNewValue()); 152 + break; 153 + case PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN: 154 + $object->setDetail('http-login', $xaction->getNewValue()); 155 + break; 156 + case PhabricatorRepositoryTransaction::TYPE_HTTP_PASS: 157 + $object->setDetail('http-pass', $xaction->getNewValue()); 115 158 break; 116 159 case PhabricatorRepositoryTransaction::TYPE_ENCODING: 117 160 // Make sure the encoding is valid by converting to UTF-8. This tests
+44 -1
src/applications/repository/storage/PhabricatorRepositoryTransaction.php
··· 14 14 const TYPE_UUID = 'repo:uuid'; 15 15 const TYPE_NOTIFY = 'repo:notify'; 16 16 const TYPE_AUTOCLOSE = 'repo:autoclose'; 17 + const TYPE_REMOTE_URI = 'repo:remote-uri'; 18 + const TYPE_SSH_LOGIN = 'repo:ssh-login'; 19 + const TYPE_SSH_KEY = 'repo:ssh-key'; 20 + const TYPE_SSH_KEYFILE = 'repo:ssh-keyfile'; 21 + const TYPE_HTTP_LOGIN = 'repo:http-login'; 22 + const TYPE_HTTP_PASS = 'repo:http-pass'; 17 23 18 24 public function getApplicationName() { 19 25 return 'repository'; ··· 187 193 $this->renderHandleLink($author_phid)); 188 194 } 189 195 break; 190 - 196 + case self::TYPE_REMOTE_URI: 197 + if (!strlen($old)) { 198 + return pht( 199 + '%s set the remote URI for this repository to "%s".', 200 + $this->renderHandleLink($author_phid), 201 + $new); 202 + } else if (!strlen($new)) { 203 + return pht( 204 + '%s removed the remote URI for this repository.', 205 + $this->renderHandleLink($author_phid)); 206 + } else { 207 + return pht( 208 + '%s changed the remote URI for this repository from "%s" to "%s".', 209 + $this->renderHandleLink($author_phid), 210 + $old, 211 + $new); 212 + } 213 + break; 214 + case self::TYPE_SSH_LOGIN: 215 + return pht( 216 + '%s updated the SSH login for this repository.', 217 + $this->renderHandleLink($author_phid)); 218 + case self::TYPE_SSH_KEY: 219 + return pht( 220 + '%s updated the SSH key for this repository.', 221 + $this->renderHandleLink($author_phid)); 222 + case self::TYPE_SSH_KEYFILE: 223 + return pht( 224 + '%s updated the SSH keyfile for this repository.', 225 + $this->renderHandleLink($author_phid)); 226 + case self::TYPE_HTTP_LOGIN: 227 + return pht( 228 + '%s updated the HTTP login for this repository.', 229 + $this->renderHandleLink($author_phid)); 230 + case self::TYPE_HTTP_PASS: 231 + return pht( 232 + '%s updated the HTTP password for this repository.', 233 + $this->renderHandleLink($author_phid)); 191 234 } 192 235 193 236 return parent::getTitle();
+4
src/view/form/PHUIFormPageView.php
··· 190 190 } 191 191 192 192 public function readFromObject($object) { 193 + foreach ($this->getControls() as $name => $control) { 194 + $control->readValueFromDictionary($object); 195 + } 196 + 193 197 return $this; 194 198 } 195 199
+16 -6
src/view/form/PHUIPagedFormView.php
··· 1 1 <?php 2 2 3 3 /** 4 - * 5 4 * @task page Managing Pages 6 5 */ 7 6 final class PHUIPagedFormView extends AphrontTagView { ··· 13 12 private $nextPage; 14 13 private $prevPage; 15 14 private $complete; 15 + private $cancelURI; 16 16 17 17 protected function canAppendChild() { 18 18 return false; ··· 211 211 return $this->name.':'.$key; 212 212 } 213 213 214 + public function setCancelURI($cancel_uri) { 215 + $this->cancelURI = $cancel_uri; 216 + return $this; 217 + } 218 + 219 + public function getCancelURI() { 220 + return $this->cancelURI; 221 + } 222 + 214 223 public function getTagContent() { 215 224 $form = id(new AphrontFormView()) 216 225 ->setUser($this->getUser()); ··· 240 249 241 250 if (!$this->isFirstPage($selected_page)) { 242 251 $submit->addBackButton(); 252 + } else if ($this->getCancelURI()) { 253 + $submit->addCancelButton($this->getCancelURI()); 243 254 } 244 255 245 256 if ($this->isLastPage($selected_page)) { ··· 261 272 ->setHeader($selected_page->getPageName()); 262 273 } 263 274 264 - return array( 265 - $header, 266 - $errors, 267 - $form, 268 - ); 275 + return id(new PHUIObjectBoxView()) 276 + ->setHeader($header) 277 + ->setFormError($errors) 278 + ->setForm($form); 269 279 } 270 280 271 281 }
+5
src/view/form/control/AphrontFormControl.php
··· 126 126 return $this; 127 127 } 128 128 129 + public function readValueFromDictionary(array $dictionary) { 130 + $this->setValue(idx($dictionary, $this->getName())); 131 + return $this; 132 + } 133 + 129 134 public function setFormPage(PHUIFormPageView $page) { 130 135 if ($this->formPage) { 131 136 throw new Exception("This control is already a member of a page!");
+16
src/view/form/control/PHUIFormMultiSubmitControl.php
··· 15 15 return $this->addButton('__submit__', $label); 16 16 } 17 17 18 + public function addCancelButton($uri, $label = null) { 19 + if ($label === null) { 20 + $label = pht('Cancel'); 21 + } 22 + 23 + $this->buttons[] = phutil_tag( 24 + 'a', 25 + array( 26 + 'class' => 'grey button', 27 + 'href' => $uri, 28 + ), 29 + $label); 30 + 31 + return $this; 32 + } 33 + 18 34 public function addButton($name, $label, $class = null) { 19 35 $this->buttons[] = phutil_tag( 20 36 'input',
+2 -1
webroot/rsrc/css/phui/phui-form-view.css
··· 108 108 margin: 4px 0 0 8px; 109 109 } 110 110 111 - .phui-form-control-multi-submit input { 111 + .phui-form-control-multi-submit input, 112 + .phui-form-control-multi-submit a { 112 113 float: right; 113 114 margin: 0.5em 0 0em 2%; 114 115 width: auto;