Add support for branch-related configuration to new Repository edit workflow
Summary: Ref T2231. Modernizes editing "Default Branch", "Track Only", and "Autoclose Only". Test Plan: See screenshots. Reviewers: btrahan, chad Reviewed By: btrahan CC: aran Maniphest Tasks: T2231 Differential Revision: https://secure.phabricator.com/D7399
This commit is contained in:
		| @@ -506,6 +506,7 @@ phutil_register_library_map(array( | ||||
|     'DiffusionRepositoryCreateController' => 'applications/diffusion/controller/DiffusionRepositoryCreateController.php', | ||||
|     'DiffusionRepositoryEditActivateController' => 'applications/diffusion/controller/DiffusionRepositoryEditActivateController.php', | ||||
|     'DiffusionRepositoryEditBasicController' => 'applications/diffusion/controller/DiffusionRepositoryEditBasicController.php', | ||||
|     'DiffusionRepositoryEditBranchesController' => 'applications/diffusion/controller/DiffusionRepositoryEditBranchesController.php', | ||||
|     'DiffusionRepositoryEditController' => 'applications/diffusion/controller/DiffusionRepositoryEditController.php', | ||||
|     'DiffusionRepositoryEditEncodingController' => 'applications/diffusion/controller/DiffusionRepositoryEditEncodingController.php', | ||||
|     'DiffusionRepositoryEditPolicyController' => 'applications/diffusion/controller/DiffusionRepositoryEditPolicyController.php', | ||||
| @@ -2677,6 +2678,7 @@ phutil_register_library_map(array( | ||||
|     'DiffusionRepositoryCreateController' => 'DiffusionController', | ||||
|     'DiffusionRepositoryEditActivateController' => 'DiffusionController', | ||||
|     'DiffusionRepositoryEditBasicController' => 'DiffusionController', | ||||
|     'DiffusionRepositoryEditBranchesController' => 'DiffusionController', | ||||
|     'DiffusionRepositoryEditController' => 'DiffusionController', | ||||
|     'DiffusionRepositoryEditEncodingController' => 'DiffusionController', | ||||
|     'DiffusionRepositoryEditPolicyController' => 'DiffusionController', | ||||
|   | ||||
| @@ -69,6 +69,7 @@ final class PhabricatorApplicationDiffusion extends PhabricatorApplication { | ||||
|             'encoding/' => 'DiffusionRepositoryEditEncodingController', | ||||
|             'activate/' => 'DiffusionRepositoryEditActivateController', | ||||
|             'policy/' => 'DiffusionRepositoryEditPolicyController', | ||||
|             'branches/' => 'DiffusionRepositoryEditBranchesController', | ||||
|           ), | ||||
|         ), | ||||
|         'inline/' => array( | ||||
|   | ||||
| @@ -0,0 +1,147 @@ | ||||
| <?php | ||||
|  | ||||
| final class DiffusionRepositoryEditBranchesController | ||||
|   extends DiffusionController { | ||||
|  | ||||
|   public function processRequest() { | ||||
|     $request = $this->getRequest(); | ||||
|     $viewer = $request->getUser(); | ||||
|     $drequest = $this->diffusionRequest; | ||||
|     $repository = $drequest->getRepository(); | ||||
|  | ||||
|     $repository = id(new PhabricatorRepositoryQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->requireCapabilities( | ||||
|         array( | ||||
|           PhabricatorPolicyCapability::CAN_VIEW, | ||||
|           PhabricatorPolicyCapability::CAN_EDIT, | ||||
|         )) | ||||
|       ->withIDs(array($repository->getID())) | ||||
|       ->executeOne(); | ||||
|  | ||||
|     if (!$repository) { | ||||
|       return new Aphront404Response(); | ||||
|     } | ||||
|  | ||||
|     switch ($repository->getVersionControlSystem()) { | ||||
|       case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: | ||||
|       case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: | ||||
|         break; | ||||
|       case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: | ||||
|         throw new Exception( | ||||
|           pht('Subversion does not support branches!')); | ||||
|       default: | ||||
|         throw new Exception( | ||||
|           pht('Repository has unknown version control system!')); | ||||
|     } | ||||
|  | ||||
|     $edit_uri = $this->getRepositoryControllerURI($repository, 'edit/'); | ||||
|  | ||||
|     $v_default = $repository->getHumanReadableDetail('default-branch'); | ||||
|     $v_track = $repository->getHumanReadableDetail('branch-filter'); | ||||
|     $v_autoclose = $repository->getHumanReadableDetail('close-commits-filter'); | ||||
|  | ||||
|     if ($request->isFormPost()) { | ||||
|       $v_default = $request->getStr('default'); | ||||
|       $v_track = $request->getStrList('track'); | ||||
|       $v_autoclose = $request->getStrList('autoclose'); | ||||
|  | ||||
|       $xactions = array(); | ||||
|       $template = id(new PhabricatorRepositoryTransaction()); | ||||
|  | ||||
|       $type_default = PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH; | ||||
|       $type_track = PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY; | ||||
|       $type_autoclose = PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY; | ||||
|  | ||||
|       $xactions[] = id(clone $template) | ||||
|         ->setTransactionType($type_default) | ||||
|         ->setNewValue($v_default); | ||||
|  | ||||
|       $xactions[] = id(clone $template) | ||||
|         ->setTransactionType($type_track) | ||||
|         ->setNewValue($v_track); | ||||
|  | ||||
|       $xactions[] = id(clone $template) | ||||
|         ->setTransactionType($type_autoclose) | ||||
|         ->setNewValue($v_autoclose); | ||||
|  | ||||
|       id(new PhabricatorRepositoryEditor()) | ||||
|         ->setContinueOnNoEffect(true) | ||||
|         ->setContentSourceFromRequest($request) | ||||
|         ->setActor($viewer) | ||||
|         ->applyTransactions($repository, $xactions); | ||||
|  | ||||
|       return id(new AphrontRedirectResponse())->setURI($edit_uri); | ||||
|     } | ||||
|  | ||||
|     $content = array(); | ||||
|  | ||||
|     $crumbs = $this->buildCrumbs(); | ||||
|     $crumbs->addCrumb( | ||||
|       id(new PhabricatorCrumbView()) | ||||
|         ->setName(pht('Edit Branches'))); | ||||
|  | ||||
|     $title = pht('Edit Branches (%s)', $repository->getName()); | ||||
|  | ||||
|     $policies = id(new PhabricatorPolicyQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->setObject($repository) | ||||
|       ->execute(); | ||||
|  | ||||
|     $form = id(new AphrontFormView()) | ||||
|       ->setUser($viewer) | ||||
|       ->appendRemarkupInstructions( | ||||
|         pht( | ||||
|           'You can choose a **Default Branch** for viewing this repository.'. | ||||
|           "\n\n". | ||||
|           'If you want to import only some branches into Diffusion, you can '. | ||||
|           'list them in **Track Only**. Other branches will be ignored. If '. | ||||
|           'you do not specify any branches, all branches are tracked.'. | ||||
|           "\n\n". | ||||
|           'If you have **Autoclose** enabled, Phabricator can close tasks and '. | ||||
|           'revisions when corresponding commits are pushed to the repository. '. | ||||
|           'If you want to autoclose objects only when commits appear on '. | ||||
|           'specific branches, you can list those branches in **Autoclose '. | ||||
|           'Only**. By default, all branches autoclose objects.')) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormTextControl()) | ||||
|           ->setName('default') | ||||
|           ->setLabel(pht('Default Branch')) | ||||
|           ->setValue($v_default) | ||||
|           ->setCaption( | ||||
|             pht('Example: %s', phutil_tag('tt', array(), 'develop')))) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormTextControl()) | ||||
|           ->setName('track') | ||||
|           ->setLabel(pht('Track Only')) | ||||
|           ->setValue($v_track) | ||||
|           ->setCaption( | ||||
|             pht('Example: %s', phutil_tag('tt', array(), 'master, develop')))) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormTextControl()) | ||||
|           ->setName('autoclose') | ||||
|           ->setLabel(pht('Autoclose Only')) | ||||
|           ->setValue($v_autoclose) | ||||
|           ->setCaption( | ||||
|             pht('Example: %s', phutil_tag('tt', array(), 'master, release')))) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormSubmitControl()) | ||||
|           ->setValue(pht('Save Branches')) | ||||
|           ->addCancelButton($edit_uri)); | ||||
|  | ||||
|     $form_box = id(new PHUIObjectBoxView()) | ||||
|       ->setHeaderText($title) | ||||
|       ->setForm($form); | ||||
|  | ||||
|     return $this->buildApplicationPage( | ||||
|       array( | ||||
|         $crumbs, | ||||
|         $form_box, | ||||
|       ), | ||||
|       array( | ||||
|         'title' => $title, | ||||
|         'device' => true, | ||||
|       )); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -8,6 +8,23 @@ final class DiffusionRepositoryEditController extends DiffusionController { | ||||
|     $drequest = $this->diffusionRequest; | ||||
|     $repository = $drequest->getRepository(); | ||||
|  | ||||
|     $is_svn = false; | ||||
|     $is_git = false; | ||||
|     $is_hg = false; | ||||
|     switch ($repository->getVersionControlSystem()) { | ||||
|       case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: | ||||
|         $is_git = true; | ||||
|         break; | ||||
|       case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: | ||||
|         $is_svn = true; | ||||
|         break; | ||||
|       case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: | ||||
|         $is_hg = true; | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     $has_branches = ($is_git || $is_hg); | ||||
|  | ||||
|     $crumbs = $this->buildCrumbs(); | ||||
|     $crumbs->addCrumb( | ||||
|       id(new PhabricatorCrumbView()) | ||||
| @@ -37,6 +54,13 @@ final class DiffusionRepositoryEditController extends DiffusionController { | ||||
|     $encoding_properties = | ||||
|       $this->buildEncodingProperties($repository, $encoding_actions); | ||||
|  | ||||
|     $branches_properties = null; | ||||
|     if ($has_branches) { | ||||
|       $branches_properties = $this->buildBranchesProperties( | ||||
|         $repository, | ||||
|         $this->buildBranchesActions($repository)); | ||||
|     } | ||||
|  | ||||
|     $xactions = id(new PhabricatorRepositoryTransactionQuery()) | ||||
|       ->setViewer($user) | ||||
|       ->withObjectPHIDs(array($repository->getPHID())) | ||||
| @@ -65,6 +89,10 @@ final class DiffusionRepositoryEditController extends DiffusionController { | ||||
|       ->addPropertyList($policy_properties) | ||||
|       ->addPropertyList($encoding_properties); | ||||
|  | ||||
|     if ($branches_properties) { | ||||
|       $obj_box->addPropertyList($branches_properties); | ||||
|     } | ||||
|  | ||||
|     return $this->buildApplicationPage( | ||||
|       array( | ||||
|         $crumbs, | ||||
| @@ -249,4 +277,58 @@ final class DiffusionRepositoryEditController extends DiffusionController { | ||||
|     return $view; | ||||
|   } | ||||
|  | ||||
|   private function buildBranchesActions(PhabricatorRepository $repository) { | ||||
|     $viewer = $this->getRequest()->getUser(); | ||||
|  | ||||
|     $view = id(new PhabricatorActionListView()) | ||||
|       ->setObjectURI($this->getRequest()->getRequestURI()) | ||||
|       ->setUser($viewer); | ||||
|  | ||||
|     $can_edit = PhabricatorPolicyFilter::hasCapability( | ||||
|       $viewer, | ||||
|       $repository, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT); | ||||
|  | ||||
|     $edit = id(new PhabricatorActionView()) | ||||
|       ->setIcon('edit') | ||||
|       ->setName(pht('Edit Branches')) | ||||
|       ->setHref( | ||||
|         $this->getRepositoryControllerURI($repository, 'edit/branches/')) | ||||
|       ->setWorkflow(!$can_edit) | ||||
|       ->setDisabled(!$can_edit); | ||||
|     $view->addAction($edit); | ||||
|  | ||||
|     return $view; | ||||
|   } | ||||
|  | ||||
|   private function buildBranchesProperties( | ||||
|     PhabricatorRepository $repository, | ||||
|     PhabricatorActionListView $actions) { | ||||
|  | ||||
|     $viewer = $this->getRequest()->getUser(); | ||||
|  | ||||
|     $view = id(new PHUIPropertyListView()) | ||||
|       ->setUser($viewer) | ||||
|       ->setActionList($actions) | ||||
|       ->addSectionHeader(pht('Branches')); | ||||
|  | ||||
|     $default_branch = nonempty( | ||||
|       $repository->getHumanReadableDetail('default-branch'), | ||||
|       phutil_tag('em', array(), $repository->getDefaultBranch())); | ||||
|     $view->addProperty(pht('Default Branch'), $default_branch); | ||||
|  | ||||
|     $track_only = nonempty( | ||||
|       $repository->getHumanReadableDetail('branch-filter'), | ||||
|       phutil_tag('em', array(), pht('Track All Branches'))); | ||||
|     $view->addProperty(pht('Track Only'), $track_only); | ||||
|  | ||||
|     $autoclose_only = nonempty( | ||||
|       $repository->getHumanReadableDetail('close-commits-filter'), | ||||
|       phutil_tag('em', array(), pht('Autoclose On All Branches'))); | ||||
|     $view->addProperty(pht('Autoclose Only'), $autoclose_only); | ||||
|  | ||||
|     return $view; | ||||
|   } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -10,6 +10,9 @@ final class PhabricatorRepositoryEditor | ||||
|     $types[] = PhabricatorRepositoryTransaction::TYPE_NAME; | ||||
|     $types[] = PhabricatorRepositoryTransaction::TYPE_DESCRIPTION; | ||||
|     $types[] = PhabricatorRepositoryTransaction::TYPE_ENCODING; | ||||
|     $types[] = PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH; | ||||
|     $types[] = PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY; | ||||
|     $types[] = PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY; | ||||
|     $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; | ||||
|     $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; | ||||
|  | ||||
| @@ -29,6 +32,12 @@ final class PhabricatorRepositoryEditor | ||||
|         return $object->getDetail('description'); | ||||
|       case PhabricatorRepositoryTransaction::TYPE_ENCODING: | ||||
|         return $object->getDetail('encoding'); | ||||
|       case PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH: | ||||
|         return $object->getDetail('default-branch'); | ||||
|       case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY: | ||||
|         return array_keys($object->getDetail('branch-filter', array())); | ||||
|       case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY: | ||||
|         return array_keys($object->getDetail('close-commits-filter', array())); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -41,6 +50,9 @@ final class PhabricatorRepositoryEditor | ||||
|       case PhabricatorRepositoryTransaction::TYPE_NAME: | ||||
|       case PhabricatorRepositoryTransaction::TYPE_DESCRIPTION: | ||||
|       case PhabricatorRepositoryTransaction::TYPE_ENCODING: | ||||
|       case PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH: | ||||
|       case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY: | ||||
|       case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY: | ||||
|         return $xaction->getNewValue(); | ||||
|     } | ||||
|   } | ||||
| @@ -59,6 +71,19 @@ final class PhabricatorRepositoryEditor | ||||
|       case PhabricatorRepositoryTransaction::TYPE_DESCRIPTION: | ||||
|         $object->setDetail('description', $xaction->getNewValue()); | ||||
|         break; | ||||
|       case PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH: | ||||
|         $object->setDetail('default-branch', $xaction->getNewValue()); | ||||
|         break; | ||||
|       case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY: | ||||
|         $object->setDetail( | ||||
|           'branch-filter', | ||||
|           array_fill_keys($xaction->getNewValue(), true)); | ||||
|         break; | ||||
|       case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY: | ||||
|         $object->setDetail( | ||||
|           'close-commits-filter', | ||||
|           array_fill_keys($xaction->getNewValue(), true)); | ||||
|         break; | ||||
|       case PhabricatorRepositoryTransaction::TYPE_ENCODING: | ||||
|         // Make sure the encoding is valid by converting to UTF-8. This tests | ||||
|         // that the user has mbstring installed, and also that they didn't type | ||||
|   | ||||
| @@ -71,6 +71,20 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO | ||||
|     return idx($this->details, $key, $default); | ||||
|   } | ||||
|  | ||||
|   public function getHumanReadableDetail($key, $default = null) { | ||||
|     $value = $this->getDetail($key, $default); | ||||
|  | ||||
|     switch ($key) { | ||||
|       case 'branch-filter': | ||||
|       case 'close-commits-filter': | ||||
|         $value = array_keys($value); | ||||
|         $value = implode(', ', $value); | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     return $value; | ||||
|   } | ||||
|  | ||||
|   public function setDetail($key, $value) { | ||||
|     $this->details[$key] = $value; | ||||
|     return $this; | ||||
|   | ||||
| @@ -7,6 +7,9 @@ final class PhabricatorRepositoryTransaction | ||||
|   const TYPE_NAME         = 'repo:name'; | ||||
|   const TYPE_DESCRIPTION  = 'repo:description'; | ||||
|   const TYPE_ENCODING     = 'repo:encoding'; | ||||
|   const TYPE_DEFAULT_BRANCH = 'repo:default-branch'; | ||||
|   const TYPE_TRACK_ONLY = 'repo:track-only'; | ||||
|   const TYPE_AUTOCLOSE_ONLY = 'repo:autoclose-only'; | ||||
|  | ||||
|   public function getApplicationName() { | ||||
|     return 'repository'; | ||||
| @@ -65,6 +68,61 @@ final class PhabricatorRepositoryTransaction | ||||
|             $old, | ||||
|             $new); | ||||
|         } | ||||
|       case self::TYPE_DEFAULT_BRANCH: | ||||
|         if (!strlen($new)) { | ||||
|           return pht( | ||||
|             '%s removed "%s" as the default branch.', | ||||
|             $this->renderHandleLink($author_phid), | ||||
|             $old); | ||||
|         } else if (!strlen($old)) { | ||||
|           return pht( | ||||
|             '%s set the default branch to "%s".', | ||||
|             $this->renderHandleLink($author_phid), | ||||
|             $new); | ||||
|         } else { | ||||
|           return pht( | ||||
|             '%s changed the default branch from "%s" to "%s".', | ||||
|             $this->renderHandleLink($author_phid), | ||||
|             $old, | ||||
|             $new); | ||||
|         } | ||||
|         break; | ||||
|       case self::TYPE_TRACK_ONLY: | ||||
|         if (!$new) { | ||||
|           return pht( | ||||
|             '%s set this repository to track all branches.', | ||||
|             $this->renderHandleLink($author_phid)); | ||||
|         } else if (!$old) { | ||||
|           return pht( | ||||
|             '%s set this repository to track branches: %s.', | ||||
|             $this->renderHandleLink($author_phid), | ||||
|             implode(', ', $new)); | ||||
|         } else { | ||||
|           return pht( | ||||
|             '%s changed track branches from "%s" to "%s".', | ||||
|             $this->renderHandleLink($author_phid), | ||||
|             implode(', ', $old), | ||||
|             implode(', ', $new)); | ||||
|         } | ||||
|         break; | ||||
|       case self::TYPE_AUTOCLOSE_ONLY: | ||||
|         if (!$new) { | ||||
|           return pht( | ||||
|             '%s set this repository to autoclose on all branches.', | ||||
|             $this->renderHandleLink($author_phid)); | ||||
|         } else if (!$old) { | ||||
|           return pht( | ||||
|             '%s set this repository to autoclose on branches: %s.', | ||||
|             $this->renderHandleLink($author_phid), | ||||
|             implode(', ', $new)); | ||||
|         } else { | ||||
|           return pht( | ||||
|             '%s changed autoclose branches from "%s" to "%s".', | ||||
|             $this->renderHandleLink($author_phid), | ||||
|             implode(', ', $old), | ||||
|             implode(', ', $new)); | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     return parent::getTitle(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 epriestley
					epriestley