public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $e_name = true;
     $e_callsign = true;
     $repository = new PhabricatorRepository();
     $type_map = PhabricatorRepositoryType::getAllRepositoryTypes();
     $errors = array();
     if ($request->isFormPost()) {
         $repository->setName($request->getStr('name'));
         $repository->setCallsign($request->getStr('callsign'));
         $repository->setVersionControlSystem($request->getStr('type'));
         if (!strlen($repository->getName())) {
             $e_name = 'Required';
             $errors[] = 'Repository name is required.';
         } else {
             $e_name = null;
         }
         if (!strlen($repository->getCallsign())) {
             $e_callsign = 'Required';
             $errors[] = 'Callsign is required.';
         } else {
             if (!preg_match('/^[A-Z]+$/', $repository->getCallsign())) {
                 $e_callsign = 'Invalid';
                 $errors[] = 'Callsign must be ALL UPPERCASE LETTERS.';
             } else {
                 $e_callsign = null;
             }
         }
         if (empty($type_map[$repository->getVersionControlSystem()])) {
             $errors[] = 'Invalid version control system.';
         }
         if (!$errors) {
             try {
                 $repository->save();
                 return id(new AphrontRedirectResponse())->setURI('/repository/edit/' . $repository->getID() . '/');
             } catch (AphrontQueryDuplicateKeyException $ex) {
                 $e_callsign = 'Duplicate';
                 $errors[] = 'Callsign must be unique. Another repository already ' . 'uses that callsign.';
             }
         }
     }
     $error_view = null;
     if ($errors) {
         $error_view = new AphrontErrorView();
         $error_view->setErrors($errors);
         $error_view->setTitle('Form Errors');
     }
     $form = new AphrontFormView();
     $form->setUser($user)->setAction('/repository/create/')->appendChild(id(new AphrontFormTextControl())->setLabel('Name')->setName('name')->setValue($repository->getName())->setError($e_name)->setCaption('Human-readable repository name.'))->appendChild('<p class="aphront-form-instructions">Select a "Callsign" &mdash; a ' . 'short, uppercase string to identify revisions in this repository. If ' . 'you choose "EX", revisions in this repository will be identified ' . 'with the prefix "rEX".</p>')->appendChild(id(new AphrontFormTextControl())->setLabel('Callsign')->setName('callsign')->setValue($repository->getCallsign())->setError($e_callsign)->setCaption('Short, UPPERCASE identifier. Once set, it can not be changed.'))->appendChild(id(new AphrontFormSelectControl())->setLabel('Type')->setName('type')->setOptions($type_map)->setValue($repository->getVersionControlSystem()))->appendChild(id(new AphrontFormSubmitControl())->setValue('Create Repository')->addCancelButton('/repository/'));
     $panel = new AphrontPanelView();
     $panel->setHeader('Create Repository');
     $panel->appendChild($form);
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
     return $this->buildStandardPageResponse(array($error_view, $panel), array('title' => 'Create Repository'));
 }
 public function buildSearchForm(AphrontFormView $form, PhabricatorSavedQuery $saved_query)
 {
     $callsigns = $saved_query->getParameter('callsigns', array());
     $types = $saved_query->getParameter('types', array());
     $types = array_fuse($types);
     $name = $saved_query->getParameter('name');
     $any_project_phids = $saved_query->getParameter('anyProjectPHIDs', array());
     if ($any_project_phids) {
         $any_project_handles = id(new PhabricatorHandleQuery())->setViewer($this->requireViewer())->withPHIDs($any_project_phids)->execute();
     } else {
         $any_project_handles = array();
     }
     $form->appendChild(id(new AphrontFormTextControl())->setName('callsigns')->setLabel(pht('Callsigns'))->setValue(implode(', ', $callsigns)))->appendChild(id(new AphrontFormTextControl())->setName('name')->setLabel(pht('Name Contains'))->setValue($name))->appendChild(id(new AphrontFormTokenizerControl())->setDatasource(new PhabricatorProjectDatasource())->setName('anyProjects')->setLabel(pht('In Any Project'))->setValue($any_project_handles))->appendChild(id(new AphrontFormSelectControl())->setName('status')->setLabel(pht('Status'))->setValue($saved_query->getParameter('status'))->setOptions($this->getStatusOptions()))->appendChild(id(new AphrontFormSelectControl())->setName('hosted')->setLabel(pht('Hosted'))->setValue($saved_query->getParameter('hosted'))->setOptions($this->getHostedOptions()));
     $type_control = id(new AphrontFormCheckboxControl())->setLabel(pht('Types'));
     $all_types = PhabricatorRepositoryType::getAllRepositoryTypes();
     foreach ($all_types as $key => $name) {
         $type_control->addCheckbox('types[]', $key, $name, isset($types[$key]));
     }
     $form->appendChild($type_control)->appendChild(id(new AphrontFormSelectControl())->setName('order')->setLabel(pht('Order'))->setValue($saved_query->getParameter('order'))->setOptions($this->getOrderOptions()));
 }
 protected function buildCustomSearchFields()
 {
     return array(id(new PhabricatorSearchStringListField())->setLabel(pht('Callsigns'))->setKey('callsigns'), id(new PhabricatorSearchTextField())->setLabel(pht('Name Contains'))->setKey('name'), id(new PhabricatorSearchSelectField())->setLabel(pht('Status'))->setKey('status')->setOptions($this->getStatusOptions()), id(new PhabricatorSearchSelectField())->setLabel(pht('Hosted'))->setKey('hosted')->setOptions($this->getHostedOptions()), id(new PhabricatorSearchCheckboxesField())->setLabel(pht('Types'))->setKey('types')->setOptions(PhabricatorRepositoryType::getAllRepositoryTypes()));
 }
 protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions)
 {
     $errors = parent::validateTransaction($object, $type, $xactions);
     switch ($type) {
         case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY:
         case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY:
             foreach ($xactions as $xaction) {
                 foreach ($xaction->getNewValue() as $pattern) {
                     // Check for invalid regular expressions.
                     $regexp = PhabricatorRepository::extractBranchRegexp($pattern);
                     if ($regexp !== null) {
                         $ok = @preg_match($regexp, '');
                         if ($ok === false) {
                             $error = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Expression "%s" is not a valid regular expression. Note ' . 'that you must include delimiters.', $regexp), $xaction);
                             $errors[] = $error;
                             continue;
                         }
                     }
                     // Check for formatting mistakes like `regex(...)` instead of
                     // `regexp(...)`.
                     $matches = null;
                     if (preg_match('/^([^(]+)\\(.*\\)\\z/', $pattern, $matches)) {
                         switch ($matches[1]) {
                             case 'regexp':
                                 break;
                             default:
                                 $error = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Matching function "%s(...)" is not recognized. Valid ' . 'functions are: regexp(...).', $matches[1]), $xaction);
                                 $errors[] = $error;
                                 break;
                         }
                     }
                 }
             }
             break;
         case PhabricatorRepositoryTransaction::TYPE_AUTOMATION_BLUEPRINTS:
             foreach ($xactions as $xaction) {
                 $old = nonempty($xaction->getOldValue(), array());
                 $new = nonempty($xaction->getNewValue(), array());
                 $add = array_diff($new, $old);
                 $invalid = PhabricatorObjectQuery::loadInvalidPHIDsForViewer($this->getActor(), $add);
                 if ($invalid) {
                     $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Some of the selected automation blueprints are invalid ' . 'or restricted: %s.', implode(', ', $invalid)), $xaction);
                 }
             }
             break;
         case PhabricatorRepositoryTransaction::TYPE_VCS:
             $vcs_map = PhabricatorRepositoryType::getAllRepositoryTypes();
             $current_vcs = $object->getVersionControlSystem();
             if (!$this->getIsNewObject()) {
                 foreach ($xactions as $xaction) {
                     if ($xaction->getNewValue() == $current_vcs) {
                         continue;
                     }
                     $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Immutable'), pht('You can not change the version control system an existing ' . 'repository uses. It can only be set when a repository is ' . 'first created.'), $xaction);
                 }
             } else {
                 $value = $object->getVersionControlSystem();
                 foreach ($xactions as $xaction) {
                     $value = $xaction->getNewValue();
                     if (empty($vcs_map[$value])) {
                         $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Specified version control system must be a VCS ' . 'recognized by Phabricator: %s.', implode(', ', array_keys($vcs_map))), $xaction);
                     }
                 }
                 if (!strlen($value)) {
                     $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('When creating a repository, you must specify a valid ' . 'underlying version control system: %s.', implode(', ', array_keys($vcs_map))), nonempty(last($xactions), null));
                     $error->setIsMissingFieldError(true);
                     $errors[] = $error;
                 }
             }
             break;
         case PhabricatorRepositoryTransaction::TYPE_NAME:
             $missing = $this->validateIsEmptyTextField($object->getName(), $xactions);
             if ($missing) {
                 $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('Repository name is required.'), nonempty(last($xactions), null));
                 $error->setIsMissingFieldError(true);
                 $errors[] = $error;
             }
             break;
         case PhabricatorRepositoryTransaction::TYPE_ACTIVATE:
             $status_map = PhabricatorRepository::getStatusMap();
             foreach ($xactions as $xaction) {
                 $status = $xaction->getNewValue();
                 if (empty($status_map[$status])) {
                     $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Repository status "%s" is not valid.', $status), $xaction);
                 }
             }
             break;
         case PhabricatorRepositoryTransaction::TYPE_ENCODING:
             foreach ($xactions as $xaction) {
                 // 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 a garbage encoding name. Note that we're converting from
                 // UTF-8 to the target encoding, because mbstring is fine with
                 // converting from a nonsense encoding.
                 $encoding = $xaction->getNewValue();
                 if (!strlen($encoding)) {
                     continue;
                 }
                 try {
                     phutil_utf8_convert('.', $encoding, 'UTF-8');
                 } catch (Exception $ex) {
                     $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Repository encoding "%s" is not valid: %s', $encoding, $ex->getMessage()), $xaction);
                 }
             }
             break;
         case PhabricatorRepositoryTransaction::TYPE_SLUG:
             foreach ($xactions as $xaction) {
                 $old = $xaction->getOldValue();
                 $new = $xaction->getNewValue();
                 if (!strlen($new)) {
                     continue;
                 }
                 if ($new === $old) {
                     continue;
                 }
                 try {
                     PhabricatorRepository::assertValidRepositorySlug($new);
                 } catch (Exception $ex) {
                     $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), $ex->getMessage(), $xaction);
                     continue;
                 }
                 $other = id(new PhabricatorRepositoryQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withSlugs(array($new))->executeOne();
                 if ($other && $other->getID() !== $object->getID()) {
                     $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Duplicate'), pht('The selected repository short name is already in use by ' . 'another repository. Choose a unique short name.'), $xaction);
                     continue;
                 }
             }
             break;
         case PhabricatorRepositoryTransaction::TYPE_CALLSIGN:
             foreach ($xactions as $xaction) {
                 $old = $xaction->getOldValue();
                 $new = $xaction->getNewValue();
                 if (!strlen($new)) {
                     continue;
                 }
                 if ($new === $old) {
                     continue;
                 }
                 try {
                     PhabricatorRepository::assertValidCallsign($new);
                 } catch (Exception $ex) {
                     $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), $ex->getMessage(), $xaction);
                     continue;
                 }
                 $other = id(new PhabricatorRepositoryQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withCallsigns(array($new))->executeOne();
                 if ($other && $other->getID() !== $object->getID()) {
                     $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Duplicate'), pht('The selected callsign ("%s") is already in use by another ' . 'repository. Choose a unique callsign.', $new), $xaction);
                     continue;
                 }
             }
             break;
         case PhabricatorRepositoryTransaction::TYPE_SYMBOLS_SOURCES:
             foreach ($xactions as $xaction) {
                 $old = $object->getSymbolSources();
                 $new = $xaction->getNewValue();
                 // If the viewer is adding new repositories, make sure they are
                 // valid and visible.
                 $add = array_diff($new, $old);
                 if (!$add) {
                     continue;
                 }
                 $repositories = id(new PhabricatorRepositoryQuery())->setViewer($this->getActor())->withPHIDs($add)->execute();
                 $repositories = mpull($repositories, null, 'getPHID');
                 foreach ($add as $phid) {
                     if (isset($repositories[$phid])) {
                         continue;
                     }
                     $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Repository ("%s") does not exist, or you do not have ' . 'permission to see it.', $phid), $xaction);
                     break;
                 }
             }
             break;
     }
     return $errors;
 }
 protected function buildCustomEditFields($object)
 {
     $viewer = $this->getViewer();
     $policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($object)->execute();
     $track_value = $object->getDetail('branch-filter', array());
     $track_value = array_keys($track_value);
     $autoclose_value = $object->getDetail('close-commits-filter', array());
     $autoclose_value = array_keys($autoclose_value);
     $automation_instructions = pht("Configure **Repository Automation** to allow Phabricator to " . "write to this repository." . "\n\n" . "IMPORTANT: This feature is new, experimental, and not supported. " . "Use it at your own risk.");
     $staging_instructions = pht("To make it easier to run integration tests and builds on code " . "under review, you can configure a **Staging Area**. When `arc` " . "creates a diff, it will push a copy of the changes to the " . "configured staging area with a corresponding tag." . "\n\n" . "IMPORTANT: This feature is new, experimental, and not supported. " . "Use it at your own risk.");
     $subpath_instructions = pht('If you want to import only part of a repository, like `trunk/`, ' . 'you can set a path in **Import Only**. Phabricator will ignore ' . 'commits which do not affect this path.');
     return array(id(new PhabricatorSelectEditField())->setKey('vcs')->setLabel(pht('Version Control System'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_VCS)->setIsConduitOnly(true)->setIsCopyable(true)->setOptions(PhabricatorRepositoryType::getAllRepositoryTypes())->setDescription(pht('Underlying repository version control system.'))->setConduitDescription(pht('Choose which version control system to use when creating a ' . 'repository.'))->setConduitTypeDescription(pht('Version control system selection.'))->setValue($object->getVersionControlSystem()), id(new PhabricatorTextEditField())->setKey('name')->setLabel(pht('Name'))->setIsRequired(true)->setTransactionType(PhabricatorRepositoryTransaction::TYPE_NAME)->setDescription(pht('The repository name.'))->setConduitDescription(pht('Rename the repository.'))->setConduitTypeDescription(pht('New repository name.'))->setValue($object->getName()), id(new PhabricatorTextEditField())->setKey('callsign')->setLabel(pht('Callsign'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_CALLSIGN)->setDescription(pht('The repository callsign.'))->setConduitDescription(pht('Change the repository callsign.'))->setConduitTypeDescription(pht('New repository callsign.'))->setValue($object->getCallsign()), id(new PhabricatorTextEditField())->setKey('shortName')->setLabel(pht('Short Name'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_SLUG)->setDescription(pht('Short, unique repository name.'))->setConduitDescription(pht('Change the repository short name.'))->setConduitTypeDescription(pht('New short name for the repository.'))->setValue($object->getRepositorySlug()), id(new PhabricatorRemarkupEditField())->setKey('description')->setLabel(pht('Description'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_DESCRIPTION)->setDescription(pht('Repository description.'))->setConduitDescription(pht('Change the repository description.'))->setConduitTypeDescription(pht('New repository description.'))->setValue($object->getDetail('description')), id(new PhabricatorTextEditField())->setKey('encoding')->setLabel(pht('Text Encoding'))->setIsCopyable(true)->setTransactionType(PhabricatorRepositoryTransaction::TYPE_ENCODING)->setDescription(pht('Default text encoding.'))->setConduitDescription(pht('Change the default text encoding.'))->setConduitTypeDescription(pht('New text encoding.'))->setValue($object->getDetail('encoding')), id(new PhabricatorBoolEditField())->setKey('allowDangerousChanges')->setLabel(pht('Allow Dangerous Changes'))->setIsCopyable(true)->setIsConduitOnly(true)->setOptions(pht('Prevent Dangerous Changes'), pht('Allow Dangerous Changes'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_DANGEROUS)->setDescription(pht('Permit dangerous changes to be made.'))->setConduitDescription(pht('Allow or prevent dangerous changes.'))->setConduitTypeDescription(pht('New protection setting.'))->setValue($object->shouldAllowDangerousChanges()), id(new PhabricatorSelectEditField())->setKey('status')->setLabel(pht('Status'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_ACTIVATE)->setIsConduitOnly(true)->setOptions(PhabricatorRepository::getStatusNameMap())->setDescription(pht('Active or inactive status.'))->setConduitDescription(pht('Active or deactivate the repository.'))->setConduitTypeDescription(pht('New repository status.'))->setValue($object->getStatus()), id(new PhabricatorTextEditField())->setKey('defaultBranch')->setLabel(pht('Default Branch'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH)->setIsCopyable(true)->setDescription(pht('Default branch name.'))->setConduitDescription(pht('Set the default branch name.'))->setConduitTypeDescription(pht('New default branch name.'))->setValue($object->getDetail('default-branch')), id(new PhabricatorTextAreaEditField())->setIsStringList(true)->setKey('trackOnly')->setLabel(pht('Track Only'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY)->setIsCopyable(true)->setDescription(pht('Track only these branches.'))->setConduitDescription(pht('Set the tracked branches.'))->setConduitTypeDescription(pht('New tracked branchs.'))->setValue($track_value), id(new PhabricatorTextAreaEditField())->setIsStringList(true)->setKey('autocloseOnly')->setLabel(pht('Autoclose Only'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY)->setIsCopyable(true)->setDescription(pht('Autoclose commits on only these branches.'))->setConduitDescription(pht('Set the autoclose branches.'))->setConduitTypeDescription(pht('New default tracked branchs.'))->setValue($autoclose_value), id(new PhabricatorTextEditField())->setKey('importOnly')->setLabel(pht('Import Only'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH)->setIsCopyable(true)->setDescription(pht('Subpath to selectively import.'))->setConduitDescription(pht('Set the subpath to import.'))->setConduitTypeDescription(pht('New subpath to import.'))->setValue($object->getDetail('svn-subpath'))->setControlInstructions($subpath_instructions), id(new PhabricatorTextEditField())->setKey('stagingAreaURI')->setLabel(pht('Staging Area URI'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_STAGING_URI)->setIsCopyable(true)->setDescription(pht('Staging area URI.'))->setConduitDescription(pht('Set the staging area URI.'))->setConduitTypeDescription(pht('New staging area URI.'))->setValue($object->getStagingURI())->setControlInstructions($staging_instructions), id(new PhabricatorDatasourceEditField())->setKey('automationBlueprintPHIDs')->setLabel(pht('Use Blueprints'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_AUTOMATION_BLUEPRINTS)->setIsCopyable(true)->setDatasource(new DrydockBlueprintDatasource())->setDescription(pht('Automation blueprints.'))->setConduitDescription(pht('Change automation blueprints.'))->setConduitTypeDescription(pht('New blueprint PHIDs.'))->setValue($object->getAutomationBlueprintPHIDs())->setControlInstructions($automation_instructions), id(new PhabricatorStringListEditField())->setKey('symbolLanguages')->setLabel(pht('Languages'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_SYMBOLS_LANGUAGE)->setIsCopyable(true)->setDescription(pht('Languages which define symbols in this repository.'))->setConduitDescription(pht('Change symbol languages for this repository.'))->setConduitTypeDescription(pht('New symbol langauges.'))->setValue($object->getSymbolLanguages()), id(new PhabricatorDatasourceEditField())->setKey('symbolRepositoryPHIDs')->setLabel(pht('Uses Symbols From'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_SYMBOLS_SOURCES)->setIsCopyable(true)->setDatasource(new DiffusionRepositoryDatasource())->setDescription(pht('Repositories to link symbols from.'))->setConduitDescription(pht('Change symbol source repositories.'))->setConduitTypeDescription(pht('New symbol repositories.'))->setValue($object->getSymbolSources()), id(new PhabricatorBoolEditField())->setKey('publish')->setLabel(pht('Publish/Notify'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_NOTIFY)->setIsCopyable(true)->setOptions(pht('Disable Notifications, Feed, and Herald'), pht('Enable Notifications, Feed, and Herald'))->setDescription(pht('Configure how changes are published.'))->setConduitDescription(pht('Change publishing options.'))->setConduitTypeDescription(pht('New notification setting.'))->setValue(!$object->getDetail('herald-disabled')), id(new PhabricatorBoolEditField())->setKey('autoclose')->setLabel(pht('Autoclose'))->setTransactionType(PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE)->setIsCopyable(true)->setOptions(pht('Disable Autoclose'), pht('Enable Autoclose'))->setDescription(pht('Stop or resume autoclosing in this repository.'))->setConduitDescription(pht('Change autoclose setting.'))->setConduitTypeDescription(pht('New autoclose setting.'))->setValue(!$object->getDetail('disable-autoclose')), id(new PhabricatorPolicyEditField())->setKey('policy.push')->setLabel(pht('Push Policy'))->setAliases(array('push'))->setIsCopyable(true)->setCapability(DiffusionPushCapability::CAPABILITY)->setPolicies($policies)->setTransactionType(PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY)->setDescription(pht('Controls who can push changes to the repository.'))->setConduitDescription(pht('Change the push policy of the repository.'))->setConduitTypeDescription(pht('New policy PHID or constant.'))->setValue($object->getPolicy(DiffusionPushCapability::CAPABILITY)));
 }