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" — 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))); }