public final function run()
 {
     $repository = $this->loadRepository();
     $expected_type = $this->getSupportedRepositoryType();
     $repo_type = $repository->getVersionControlSystem();
     if ($repo_type != $expected_type) {
         $repo_type_name = PhabricatorRepositoryType::getNameForRepositoryType($repo_type);
         $expected_type_name = PhabricatorRepositoryType::getNameForRepositoryType($expected_type);
         $repo_name = $repository->getName() . ' (' . $repository->getCallsign() . ')';
         throw new Exception("This daemon pulls '{$expected_type_name}' repositories, but the " . "repository '{$repo_name}' is a '{$repo_type_name}' repository.");
     }
     $tracked = $repository->isTracked();
     if (!$tracked) {
         throw new Exception("Tracking is not enabled for this repository.");
     }
     $local_path = $repository->getDetail('local-path');
     if (!$local_path) {
         throw new Exception("No local path is available for this repository.");
     }
     while (true) {
         if (!Filesystem::pathExists($local_path)) {
             execx('mkdir -p %s', dirname($local_path));
             $this->executeCreate($repository, $local_path);
         } else {
             $this->executeUpdate($repository, $local_path);
         }
         $this->sleep($repository->getDetail('pull-frequency', 15));
     }
 }
 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 processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $is_admin = $user->getIsAdmin();
     $repos = id(new PhabricatorRepositoryQuery())->setViewer($user)->execute();
     $repos = msort($repos, 'getName');
     $rows = array();
     foreach ($repos as $repo) {
         if ($repo->isTracked()) {
             $diffusion_link = phutil_tag('a', array('href' => '/diffusion/' . $repo->getCallsign() . '/'), 'View in Diffusion');
         } else {
             $diffusion_link = phutil_tag('em', array(), 'Not Tracked');
         }
         $rows[] = array($repo->getCallsign(), $repo->getName(), PhabricatorRepositoryType::getNameForRepositoryType($repo->getVersionControlSystem()), $diffusion_link, phutil_tag('a', array('class' => 'button small grey', 'href' => '/diffusion/' . $repo->getCallsign() . '/edit/'), 'Edit'));
     }
     $table = new AphrontTableView($rows);
     $table->setHeaders(array('Callsign', 'Repository', 'Type', 'Diffusion', ''));
     $table->setColumnClasses(array(null, 'wide', null, null, 'action'));
     $table->setColumnVisibility(array(true, true, true, true, $is_admin));
     $panel = new AphrontPanelView();
     $panel->setHeader('Repositories');
     if ($is_admin) {
         $panel->setCreateButton('Create New Repository', '/diffusion/new/');
     }
     $panel->appendChild($table);
     $panel->setNoBackground();
     $projects = id(new PhabricatorRepositoryArcanistProject())->loadAll();
     $rows = array();
     foreach ($projects as $project) {
         $repo = idx($repos, $project->getRepositoryID());
         if ($repo) {
             $repo_name = $repo->getName();
         } else {
             $repo_name = '-';
         }
         $rows[] = array($project->getName(), $repo_name, phutil_tag('a', array('href' => '/repository/project/edit/' . $project->getID() . '/', 'class' => 'button grey small'), 'Edit'), javelin_tag('a', array('href' => '/repository/project/delete/' . $project->getID() . '/', 'class' => 'button grey small', 'sigil' => 'workflow'), 'Delete'));
     }
     $project_table = new AphrontTableView($rows);
     $project_table->setHeaders(array('Project ID', 'Repository', '', ''));
     $project_table->setColumnClasses(array('', 'wide', 'action', 'action'));
     $project_table->setColumnVisibility(array(true, true, $is_admin, $is_admin));
     $project_panel = new AphrontPanelView();
     $project_panel->setHeader('Arcanist Projects');
     $project_panel->appendChild($project_table);
     $project_panel->setNoBackground();
     return $this->buildStandardPageResponse(array($panel, $project_panel), array('title' => 'Repository List'));
 }
 private function buildVCSTypeResponse()
 {
     $vcs_types = PhabricatorRepositoryType::getRepositoryTypeMap();
     $request = $this->getRequest();
     $viewer = $this->getViewer();
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Create Repository'));
     $crumbs->setBorder(true);
     $title = pht('Choose Repository Type');
     $header = id(new PHUIHeaderView())->setHeader(pht('Create Repository'))->setHeaderIcon('fa-plus-square');
     $layout = id(new AphrontMultiColumnView())->setFluidLayout(true);
     $create_uri = $request->getRequestURI();
     foreach ($vcs_types as $vcs_key => $vcs_type) {
         $action = id(new PHUIActionPanelView())->setIcon(idx($vcs_type, 'icon'))->setHeader(idx($vcs_type, 'create.header'))->setHref($create_uri->alter('vcs', $vcs_key))->setSubheader(idx($vcs_type, 'create.subheader'));
         $layout->addColumn($action);
     }
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter($layout);
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
 }
 private function buildVCSTypeResponse()
 {
     $vcs_types = PhabricatorRepositoryType::getRepositoryTypeMap();
     $request = $this->getRequest();
     $viewer = $this->getViewer();
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Create Repository'));
     $crumbs->setBorder(true);
     $title = pht('Choose Repository Type');
     $header = id(new PHUIHeaderView())->setHeader(pht('Create Repository'))->setHeaderIcon('fa-plus-square');
     $layout = id(new AphrontMultiColumnView())->setFluidLayout(true);
     $create_uri = $request->getRequestURI();
     foreach ($vcs_types as $vcs_key => $vcs_type) {
         $action = id(new PHUIActionPanelView())->setIcon(idx($vcs_type, 'icon'))->setHeader(idx($vcs_type, 'create.header'))->setHref($create_uri->alter('vcs', $vcs_key))->setSubheader(idx($vcs_type, 'create.subheader'));
         $layout->addColumn($action);
     }
     $hints = id(new AphrontMultiColumnView())->setFluidLayout(true);
     $observe_href = PhabricatorEnv::getDoclink('Diffusion User Guide: Existing Repositories');
     $hints->addColumn(id(new PHUIActionPanelView())->setIcon('fa-book')->setHeader(pht('Import or Observe an Existing Repository'))->setHref($observe_href)->setSubheader(pht('Review the documentation describing how to import or observe an ' . 'existing repository.')));
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter(array($layout, phutil_tag('br'), $hints));
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
 }
 public function loadResults()
 {
     $viewer = $this->getViewer();
     $raw_query = $this->getRawQuery();
     $query = id(new PhabricatorRepositoryQuery())->setOrder('name')->withDatasourceQuery($raw_query);
     $repos = $this->executeQuery($query);
     $type_icon = id(new PhabricatorRepositoryRepositoryPHIDType())->getTypeIcon();
     $image_sprite = "phabricator-search-icon phui-font-fa phui-icon-view {$type_icon}";
     $results = array();
     foreach ($repos as $repository) {
         $monogram = $repository->getMonogram();
         $name = $repository->getName();
         $display_name = "{$monogram} {$name}";
         $parts = array();
         $parts[] = $name;
         $slug = $repository->getRepositorySlug();
         if (strlen($slug)) {
             $parts[] = $slug;
         }
         $callsign = $repository->getCallsign();
         if ($callsign) {
             $parts[] = $callsign;
         }
         foreach ($repository->getAllMonograms() as $monogram) {
             $parts[] = $monogram;
         }
         $name = implode(' ', $parts);
         $vcs = $repository->getVersionControlSystem();
         $vcs_type = PhabricatorRepositoryType::getNameForRepositoryType($vcs);
         $result = id(new PhabricatorTypeaheadResult())->setName($name)->setDisplayName($display_name)->setURI($repository->getURI())->setPHID($repository->getPHID())->setPriorityString($repository->getMonogram())->setPriorityType('repo')->setImageSprite($image_sprite)->setDisplayType(pht('Repository'))->addAttribute($vcs_type);
         if (!$repository->isTracked()) {
             $result->setClosed(pht('Inactive'));
         }
         $results[] = $result;
     }
     return $results;
 }
 protected function renderResultList(array $repositories, PhabricatorSavedQuery $query, array $handles)
 {
     assert_instances_of($repositories, 'PhabricatorRepository');
     $viewer = $this->requireViewer();
     $list = new PHUIObjectItemListView();
     foreach ($repositories as $repository) {
         $id = $repository->getID();
         $item = id(new PHUIObjectItemView())->setUser($viewer)->setHeader($repository->getName())->setObjectName('r' . $repository->getCallsign())->setHref($this->getApplicationURI($repository->getCallsign() . '/'));
         $commit = $repository->getMostRecentCommit();
         if ($commit) {
             $commit_link = DiffusionView::linkCommit($repository, $commit->getCommitIdentifier(), $commit->getSummary());
             $item->setSubhead($commit_link);
             $item->setEpoch($commit->getEpoch());
         }
         $item->addIcon('none', PhabricatorRepositoryType::getNameForRepositoryType($repository->getVersionControlSystem()));
         $size = $repository->getCommitCount();
         if ($size) {
             $history_uri = DiffusionRequest::generateDiffusionURI(array('callsign' => $repository->getCallsign(), 'action' => 'history'));
             $item->addAttribute(phutil_tag('a', array('href' => $history_uri), pht('%s Commit(s)', new PhutilNumber($size))));
         } else {
             $item->addAttribute(pht('No Commits'));
         }
         $project_handles = array_select_keys($handles, $repository->getProjectPHIDs());
         if ($project_handles) {
             $item->addAttribute(id(new PHUIHandleTagListView())->setSlim(true)->setHandles($project_handles));
         }
         if (!$repository->isTracked()) {
             $item->setDisabled(true);
             $item->addIcon('disable-grey', pht('Inactive'));
         }
         $list->addItem($item);
     }
     return $list;
 }
 private function buildBasicProperties(PhabricatorRepository $repository, PhabricatorActionListView $actions)
 {
     $viewer = $this->getRequest()->getUser();
     $view = id(new PHUIPropertyListView())->setUser($viewer)->setObject($repository)->setActionList($actions);
     $type = PhabricatorRepositoryType::getNameForRepositoryType($repository->getVersionControlSystem());
     $view->addProperty(pht('Type'), $type);
     $view->addProperty(pht('Callsign'), $repository->getCallsign());
     $clone_name = $repository->getDetail('clone-name');
     if ($repository->isHosted()) {
         $view->addProperty(pht('Clone/Checkout As'), $clone_name ? $clone_name . '/' : phutil_tag('em', array(), $repository->getCloneName() . '/'));
     }
     $view->invokeWillRenderEvent();
     $view->addProperty(pht('Status'), $this->buildRepositoryStatus($repository));
     $view->addProperty(pht('Update Frequency'), $this->buildRepositoryUpdateInterval($repository));
     $description = $repository->getDetail('description');
     $view->addSectionHeader(pht('Description'), PHUIPropertyListView::ICON_SUMMARY);
     if (!strlen($description)) {
         $description = phutil_tag('em', array(), pht('No description provided.'));
     } else {
         $description = PhabricatorMarkupEngine::renderOneObject($repository, 'description', $viewer);
     }
     $view->addTextContent($description);
     return $view;
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $shortcuts = id(new PhabricatorRepositoryShortcut())->loadAll();
     if ($shortcuts) {
         $shortcuts = msort($shortcuts, 'getSequence');
         $rows = array();
         foreach ($shortcuts as $shortcut) {
             $rows[] = array(phutil_render_tag('a', array('href' => $shortcut->getHref()), phutil_escape_html($shortcut->getName())), phutil_escape_html($shortcut->getDescription()));
         }
         $shortcut_table = new AphrontTableView($rows);
         $shortcut_table->setHeaders(array('Link', ''));
         $shortcut_table->setColumnClasses(array('pri', 'wide'));
         $shortcut_panel = new AphrontPanelView();
         $shortcut_panel->setHeader('Shortcuts');
         $shortcut_panel->appendChild($shortcut_table);
     } else {
         $shortcut_panel = null;
     }
     $repository = new PhabricatorRepository();
     $repositories = $repository->loadAll();
     foreach ($repositories as $key => $repo) {
         if (!$repo->isTracked()) {
             unset($repositories[$key]);
         }
     }
     $repository_ids = mpull($repositories, 'getID');
     $summaries = array();
     $commits = array();
     if ($repository_ids) {
         $summaries = queryfx_all($repository->establishConnection('r'), 'SELECT * FROM %T WHERE repositoryID IN (%Ld)', PhabricatorRepository::TABLE_SUMMARY, $repository_ids);
         $summaries = ipull($summaries, null, 'repositoryID');
         $commit_ids = array_filter(ipull($summaries, 'lastCommitID'));
         if ($commit_ids) {
             $commit = new PhabricatorRepositoryCommit();
             $commits = $commit->loadAllWhere('id IN (%Ld)', $commit_ids);
             $commits = mpull($commits, null, 'getRepositoryID');
         }
     }
     $rows = array();
     foreach ($repositories as $repository) {
         $id = $repository->getID();
         $commit = idx($commits, $id);
         $size = idx(idx($summaries, $id, array()), 'size', 0);
         $date = '-';
         $time = '-';
         if ($commit) {
             $date = phabricator_date($commit->getEpoch(), $user);
             $time = phabricator_time($commit->getEpoch(), $user);
         }
         $rows[] = array(phutil_render_tag('a', array('href' => '/diffusion/' . $repository->getCallsign() . '/'), phutil_escape_html($repository->getName())), phutil_escape_html($repository->getDetail('description')), PhabricatorRepositoryType::getNameForRepositoryType($repository->getVersionControlSystem()), $size ? number_format($size) : '-', $commit ? DiffusionView::linkCommit($repository, $commit->getCommitIdentifier()) : '-', $date, $time);
     }
     $repository_tool_uri = PhabricatorEnv::getProductionURI('/repository/');
     $repository_tool = phutil_render_tag('a', array('href' => $repository_tool_uri), 'repository tool');
     $no_repositories_txt = 'This instance of Phabricator does not have any ' . 'configured repositories. ';
     if ($user->getIsAdmin()) {
         $no_repositories_txt .= 'To setup one or more repositories, visit the ' . $repository_tool . '.';
     } else {
         $no_repositories_txt .= 'Ask an administrator to setup one or more ' . 'repositories via the ' . $repository_tool . '.';
     }
     $table = new AphrontTableView($rows);
     $table->setNoDataString($no_repositories_txt);
     $table->setHeaders(array('Repository', 'Description', 'VCS', 'Commits', 'Last', 'Date', 'Time'));
     $table->setColumnClasses(array('pri', 'wide', '', 'n', 'n', '', 'right'));
     $panel = new AphrontPanelView();
     $panel->setHeader('Browse Repositories');
     $panel->appendChild($table);
     $crumbs = $this->buildCrumbs();
     return $this->buildStandardPageResponse(array($crumbs, $shortcut_panel, $panel), array('title' => 'Diffusion'));
 }
 private function buildBasics()
 {
     $repository = $this->getRepository();
     $viewer = $this->getViewer();
     $view = id(new PHUIPropertyListView())->setViewer($viewer)->setActionList($this->newActions());
     $name = $repository->getName();
     $view->addProperty(pht('Name'), $name);
     $type = PhabricatorRepositoryType::getNameForRepositoryType($repository->getVersionControlSystem());
     $view->addProperty(pht('Type'), $type);
     $callsign = $repository->getCallsign();
     if (!strlen($callsign)) {
         $callsign = phutil_tag('em', array(), pht('No Callsign'));
     }
     $view->addProperty(pht('Callsign'), $callsign);
     $short_name = $repository->getRepositorySlug();
     if ($short_name === null) {
         $short_name = $repository->getCloneName();
         $short_name = phutil_tag('em', array(), $short_name);
     }
     $view->addProperty(pht('Short Name'), $short_name);
     $encoding = $repository->getDetail('encoding');
     if (!$encoding) {
         $encoding = phutil_tag('em', array(), pht('Use Default (UTF-8)'));
     }
     $view->addProperty(pht('Encoding'), $encoding);
     $can_dangerous = $repository->canAllowDangerousChanges();
     if (!$can_dangerous) {
         $dangerous = phutil_tag('em', array(), pht('Not Preventable'));
     } else {
         $should_dangerous = $repository->shouldAllowDangerousChanges();
         if ($should_dangerous) {
             $dangerous = pht('Allowed');
         } else {
             $dangerous = pht('Not Allowed');
         }
     }
     $view->addProperty(pht('Dangerous Changes'), $dangerous);
     return $view;
 }
 private function buildBasicProperties(PhabricatorRepository $repository, PhabricatorActionListView $actions)
 {
     $viewer = $this->getRequest()->getUser();
     $view = id(new PHUIPropertyListView())->setUser($viewer)->setObject($repository)->setActionList($actions);
     $type = PhabricatorRepositoryType::getNameForRepositoryType($repository->getVersionControlSystem());
     $view->addProperty(pht('Type'), $type);
     $callsign = $repository->getCallsign();
     if (!strlen($callsign)) {
         $callsign = phutil_tag('em', array(), pht('No Callsign'));
     }
     $view->addProperty(pht('Callsign'), $callsign);
     $short_name = $repository->getRepositorySlug();
     if ($short_name === null) {
         $short_name = $repository->getCloneName();
         $short_name = phutil_tag('em', array(), $short_name);
     }
     $view->addProperty(pht('Short Name'), $short_name);
     $view->invokeWillRenderEvent();
     $view->addProperty(pht('Status'), $this->buildRepositoryStatus($repository));
     $view->addProperty(pht('Update Frequency'), $this->buildRepositoryUpdateInterval($repository));
     $description = $repository->getDetail('description');
     $view->addSectionHeader(pht('Description'), PHUIPropertyListView::ICON_SUMMARY);
     if (!strlen($description)) {
         $description = phutil_tag('em', array(), pht('No description provided.'));
     } else {
         $description = new PHUIRemarkupView($viewer, $description);
     }
     $view->addTextContent($description);
     return $view;
 }
 protected function renderResultList(array $repositories, PhabricatorSavedQuery $query, array $handles)
 {
     assert_instances_of($repositories, 'PhabricatorRepository');
     $viewer = $this->requireViewer();
     $list = new PHUIObjectItemListView();
     foreach ($repositories as $repository) {
         $id = $repository->getID();
         $item = id(new PHUIObjectItemView())->setUser($viewer)->setObject($repository)->setHeader($repository->getName())->setObjectName($repository->getMonogram())->setHref($repository->getURI());
         $commit = $repository->getMostRecentCommit();
         if ($commit) {
             $commit_link = phutil_tag('a', array('href' => $commit->getURI()), pht('%s: %s', $commit->getLocalName(), $commit->getSummary()));
             $item->setSubhead($commit_link);
             $item->setEpoch($commit->getEpoch());
         }
         $item->addIcon('none', PhabricatorRepositoryType::getNameForRepositoryType($repository->getVersionControlSystem()));
         $size = $repository->getCommitCount();
         if ($size) {
             $history_uri = $repository->generateURI(array('action' => 'history'));
             $item->addAttribute(phutil_tag('a', array('href' => $history_uri), pht('%s Commit(s)', new PhutilNumber($size))));
         } else {
             $item->addAttribute(pht('No Commits'));
         }
         $project_handles = array_select_keys($handles, $repository->getProjectPHIDs());
         if ($project_handles) {
             $item->addAttribute(id(new PHUIHandleTagListView())->setSlim(true)->setHandles($project_handles));
         }
         if (!$repository->isTracked()) {
             $item->setDisabled(true);
             $item->addIcon('disable-grey', pht('Inactive'));
         } else {
             if ($repository->isImporting()) {
                 $item->addIcon('fa-clock-o indigo', pht('Importing...'));
             }
         }
         $list->addItem($item);
     }
     $result = new PhabricatorApplicationSearchResultView();
     $result->setObjectList($list);
     $result->setNoDataString(pht('No repositories found for this query.'));
     return $result;
 }
 private function buildBasicProperties(PhabricatorRepository $repository, PhabricatorActionListView $actions)
 {
     $viewer = $this->getRequest()->getUser();
     $view = id(new PHUIPropertyListView())->setUser($viewer)->setActionList($actions);
     $type = PhabricatorRepositoryType::getNameForRepositoryType($repository->getVersionControlSystem());
     $view->addProperty(pht('Type'), $type);
     $view->addProperty(pht('Callsign'), $repository->getCallsign());
     $clone_name = $repository->getDetail('clone-name');
     if ($repository->isHosted()) {
         $view->addProperty(pht('Clone/Checkout As'), $clone_name ? $clone_name . '/' : phutil_tag('em', array(), $repository->getCloneName() . '/'));
     }
     $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($repository->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
     if ($project_phids) {
         $this->loadHandles($project_phids);
         $project_text = $this->renderHandlesForPHIDs($project_phids);
     } else {
         $project_text = phutil_tag('em', array(), pht('None'));
     }
     $view->addProperty(pht('Projects'), $project_text);
     $view->addProperty(pht('Status'), $this->buildRepositoryStatus($repository));
     $view->addProperty(pht('Update Frequency'), $this->buildRepositoryUpdateInterval($repository));
     $description = $repository->getDetail('description');
     $view->addSectionHeader(pht('Description'));
     if (!strlen($description)) {
         $description = phutil_tag('em', array(), pht('No description provided.'));
     } else {
         $description = PhabricatorMarkupEngine::renderOneObject($repository, 'description', $viewer);
     }
     $view->addTextContent($description);
     return $view;
 }
 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)));
 }