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 createMenuItem(PhabricatorUser $viewer, DifferentialRevision $revision, PhabricatorRepository $repository)
 {
     $vcs = $repository->getVersionControlSystem();
     if ($vcs !== PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL) {
         return;
     }
     if (!$repository->isHosted()) {
         return;
     }
     return $this->createActionView($revision, pht('Land to Hosted Repository'));
 }
Пример #3
0
 protected static final function initQueryObject($base_class, PhabricatorRepository $repository)
 {
     $map = array(PhabricatorRepositoryType::REPOSITORY_TYPE_GIT => 'Git', PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL => 'Mercurial', PhabricatorRepositoryType::REPOSITORY_TYPE_SVN => 'Svn');
     $name = idx($map, $repository->getVersionControlSystem());
     if (!$name) {
         throw new Exception(pht('Unsupported VCS!'));
     }
     $class = str_replace('Diffusion', 'Diffusion' . $name, $base_class);
     $obj = new $class();
     return $obj;
 }
Пример #4
0
 public static final function nameCommit(PhabricatorRepository $repository, $commit)
 {
     switch ($repository->getVersionControlSystem()) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $commit_name = substr($commit, 0, 12);
             break;
         default:
             $commit_name = $commit;
             break;
     }
     $callsign = $repository->getCallsign();
     return "r{$callsign}{$commit_name}";
 }
 /**
  * returns PhabricatorActionView or an array of PhabricatorActionView or null.
  */
 public function createMenuItem(PhabricatorUser $viewer, DifferentialRevision $revision, PhabricatorRepository $repository)
 {
     $vcs = $repository->getVersionControlSystem();
     if ($vcs !== PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) {
         return;
     }
     if ($repository->isHosted()) {
         return;
     }
     try {
         // These throw when failing.
         $this->init($viewer, $repository);
         $this->findGitHubRepo($repository);
     } catch (Exception $e) {
         return;
     }
     return $this->createActionView($revision, pht('Land to GitHub'))->setIcon('fa-cloud-upload');
 }
 private function parseCommit(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit)
 {
     switch ($repository->getVersionControlSystem()) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
             $parser = 'PhabricatorRepositoryGitCommitChangeParserWorker';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $parser = 'PhabricatorRepositoryMercurialCommitChangeParserWorker';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             $parser = 'PhabricatorRepositorySvnCommitChangeParserWorker';
             break;
         default:
             throw new Exception(pht('No support yet.'));
     }
     $parser_object = newv($parser, array(array()));
     return $parser_object->parseChangesForUnitTest($repository, $commit);
 }
 public function createMenuItem(PhabricatorUser $viewer, DifferentialRevision $revision, PhabricatorRepository $repository)
 {
     $vcs = $repository->getVersionControlSystem();
     if ($vcs !== PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) {
         return;
     }
     if (!$repository->isHosted()) {
         return;
     }
     if (!$repository->isWorkingCopyBare()) {
         return;
     }
     // TODO: This temporarily disables this action, because it doesn't work
     // and is confusing to users. If you want to use it, comment out this line
     // for now and we'll provide real support eventually.
     return;
     return $this->createActionView($revision, pht('Land to Hosted Repository'));
 }
 public function handleProtocols(PhabricatorRepository $repository)
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $type = $repository->getVersionControlSystem();
     $is_svn = $type == PhabricatorRepositoryType::REPOSITORY_TYPE_SVN;
     $v_http_mode = $repository->getDetail('serve-over-http', PhabricatorRepository::SERVE_OFF);
     $v_ssh_mode = $repository->getDetail('serve-over-ssh', PhabricatorRepository::SERVE_OFF);
     $edit_uri = $this->getRepositoryControllerURI($repository, 'edit/');
     $prev_uri = $this->getRepositoryControllerURI($repository, 'edit/hosting/');
     if ($request->isFormPost()) {
         $v_http_mode = $request->getStr('http');
         $v_ssh_mode = $request->getStr('ssh');
         $xactions = array();
         $template = id(new PhabricatorRepositoryTransaction());
         $type_http = PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP;
         $type_ssh = PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH;
         if (!$is_svn) {
             $xactions[] = id(clone $template)->setTransactionType($type_http)->setNewValue($v_http_mode);
         }
         $xactions[] = id(clone $template)->setTransactionType($type_ssh)->setNewValue($v_ssh_mode);
         id(new PhabricatorRepositoryEditor())->setContinueOnNoEffect(true)->setContentSourceFromRequest($request)->setActor($user)->applyTransactions($repository, $xactions);
         return id(new AphrontRedirectResponse())->setURI($edit_uri);
     }
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Edit Protocols'));
     $title = pht('Edit Protocols (%s)', $repository->getName());
     $rw_message = pht('Phabricator will serve a read-write copy of this repository.');
     if (!$repository->isHosted()) {
         $rw_message = array($rw_message, phutil_tag('br'), phutil_tag('br'), pht('%s: This repository is hosted elsewhere, so Phabricator can not ' . 'perform writes. This mode will act like "Read Only" for ' . 'repositories hosted elsewhere.', phutil_tag('strong', array(), 'WARNING')));
     }
     $ssh_control = id(new AphrontFormRadioButtonControl())->setName('ssh')->setLabel(pht('SSH'))->setValue($v_ssh_mode)->addButton(PhabricatorRepository::SERVE_OFF, PhabricatorRepository::getProtocolAvailabilityName(PhabricatorRepository::SERVE_OFF), pht('Phabricator will not serve this repository over SSH.'))->addButton(PhabricatorRepository::SERVE_READONLY, PhabricatorRepository::getProtocolAvailabilityName(PhabricatorRepository::SERVE_READONLY), pht('Phabricator will serve a read-only copy of this repository ' . 'over SSH.'))->addButton(PhabricatorRepository::SERVE_READWRITE, PhabricatorRepository::getProtocolAvailabilityName(PhabricatorRepository::SERVE_READWRITE), $rw_message);
     $http_control = id(new AphrontFormRadioButtonControl())->setName('http')->setLabel(pht('HTTP'))->setValue($v_http_mode)->addButton(PhabricatorRepository::SERVE_OFF, PhabricatorRepository::getProtocolAvailabilityName(PhabricatorRepository::SERVE_OFF), pht('Phabricator will not serve this repository over HTTP.'))->addButton(PhabricatorRepository::SERVE_READONLY, PhabricatorRepository::getProtocolAvailabilityName(PhabricatorRepository::SERVE_READONLY), pht('Phabricator will serve a read-only copy of this repository ' . 'over HTTP.'))->addButton(PhabricatorRepository::SERVE_READWRITE, PhabricatorRepository::getProtocolAvailabilityName(PhabricatorRepository::SERVE_READWRITE), $rw_message);
     if ($is_svn) {
         $http_control = id(new AphrontFormMarkupControl())->setLabel(pht('HTTP'))->setValue(phutil_tag('em', array(), pht('Phabricator does not currently support HTTP access to ' . 'Subversion repositories.')));
     }
     $form = id(new AphrontFormView())->setUser($user)->appendRemarkupInstructions(pht('Phabricator can serve repositories over various protocols. You can ' . 'configure server protocols here.'))->appendChild($ssh_control);
     if (!PhabricatorEnv::getEnvConfig('diffusion.allow-http-auth')) {
         $form->appendRemarkupInstructions(pht('NOTE: The configuration setting [[ %s | %s ]] is currently ' . 'disabled. You must enable it to activate authenticated access ' . 'to repositories over HTTP.', '/config/edit/diffusion.allow-http-auth/', 'diffusion.allow-http-auth'));
     }
     $form->appendChild($http_control)->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Save Changes'))->addCancelButton($prev_uri, pht('Back')));
     $object_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setForm($form);
     return $this->buildApplicationPage(array($crumbs, $object_box), array('title' => $title));
 }
 /**
  * Returns PhabricatorActionView or an array of PhabricatorActionView or null.
  */
 public function createMenuItem(PhabricatorUser $viewer, DifferentialRevision $revision, PhabricatorRepository $repository)
 {
     // TODO: This temporarily disables this action, because it doesn't work
     // and is confusing to users. If you want to use it, comment out this line
     // for now and we'll provide real support eventually.
     return;
     $vcs = $repository->getVersionControlSystem();
     if ($vcs !== PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) {
         return;
     }
     if ($repository->isHosted()) {
         return;
     }
     try {
         // These throw when failing.
         $this->init($viewer, $repository);
         $this->findGitHubRepo($repository);
     } catch (Exception $e) {
         return;
     }
     return $this->createActionView($revision, pht('Land to GitHub'))->setIcon('fa-cloud-upload');
 }
 private function buildRepositoryStatus(PhabricatorRepository $repository)
 {
     $viewer = $this->getRequest()->getUser();
     $is_cluster = $repository->getAlmanacServicePHID();
     $view = new PHUIStatusListView();
     $messages = id(new PhabricatorRepositoryStatusMessage())->loadAllWhere('repositoryID = %d', $repository->getID());
     $messages = mpull($messages, null, 'getStatusType');
     if ($repository->isTracked()) {
         $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')->setTarget(pht('Repository Active')));
     } else {
         $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_WARNING, 'bluegrey')->setTarget(pht('Repository Inactive'))->setNote(pht('Activate this repository to begin or resume import.')));
         return $view;
     }
     $binaries = array();
     $svnlook_check = false;
     switch ($repository->getVersionControlSystem()) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
             $binaries[] = 'git';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             $binaries[] = 'svn';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $binaries[] = 'hg';
             break;
     }
     if ($repository->isHosted()) {
         if ($repository->getServeOverHTTP() != PhabricatorRepository::SERVE_OFF) {
             switch ($repository->getVersionControlSystem()) {
                 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
                     $binaries[] = 'git-http-backend';
                     break;
                 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
                     $binaries[] = 'svnserve';
                     $binaries[] = 'svnadmin';
                     $binaries[] = 'svnlook';
                     $svnlook_check = true;
                     break;
                 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
                     $binaries[] = 'hg';
                     break;
             }
         }
         if ($repository->getServeOverSSH() != PhabricatorRepository::SERVE_OFF) {
             switch ($repository->getVersionControlSystem()) {
                 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
                     $binaries[] = 'git-receive-pack';
                     $binaries[] = 'git-upload-pack';
                     break;
                 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
                     $binaries[] = 'svnserve';
                     $binaries[] = 'svnadmin';
                     $binaries[] = 'svnlook';
                     $svnlook_check = true;
                     break;
                 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
                     $binaries[] = 'hg';
                     break;
             }
         }
     }
     $binaries = array_unique($binaries);
     if (!$is_cluster) {
         // We're only checking for binaries if we aren't running with a cluster
         // configuration. In theory, we could check for binaries on the
         // repository host machine, but we'd need to make this more complicated
         // to do that.
         foreach ($binaries as $binary) {
             $where = Filesystem::resolveBinary($binary);
             if (!$where) {
                 $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')->setTarget(pht('Missing Binary %s', phutil_tag('tt', array(), $binary)))->setNote(pht("Unable to find this binary in the webserver's PATH. You may " . "need to configure %s.", $this->getEnvConfigLink())));
             } else {
                 $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')->setTarget(pht('Found Binary %s', phutil_tag('tt', array(), $binary)))->setNote(phutil_tag('tt', array(), $where)));
             }
         }
         // This gets checked generically above. However, for svn commit hooks, we
         // need this to be in environment.append-paths because subversion strips
         // PATH.
         if ($svnlook_check) {
             $where = Filesystem::resolveBinary('svnlook');
             if ($where) {
                 $path = substr($where, 0, strlen($where) - strlen('svnlook'));
                 $dirs = PhabricatorEnv::getEnvConfig('environment.append-paths');
                 $in_path = false;
                 foreach ($dirs as $dir) {
                     if (Filesystem::isDescendant($path, $dir)) {
                         $in_path = true;
                         break;
                     }
                 }
                 if (!$in_path) {
                     $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')->setTarget(pht('Missing Binary %s', phutil_tag('tt', array(), $binary)))->setNote(pht('Unable to find this binary in `%s`. ' . 'You need to configure %s and include %s.', 'environment.append-paths', $this->getEnvConfigLink(), $path)));
                 }
             }
         }
     }
     $doc_href = PhabricatorEnv::getDocLink('Managing Daemons with phd');
     $daemon_instructions = pht('Use %s to start daemons. See %s.', phutil_tag('tt', array(), 'bin/phd start'), phutil_tag('a', array('href' => $doc_href), pht('Managing Daemons with phd')));
     $pull_daemon = id(new PhabricatorDaemonLogQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)->withDaemonClasses(array('PhabricatorRepositoryPullLocalDaemon'))->setLimit(1)->execute();
     if ($pull_daemon) {
         // TODO: In a cluster environment, we need a daemon on this repository's
         // host, specifically, and we aren't checking for that right now. This
         // is a reasonable proxy for things being more-or-less correctly set up,
         // though.
         $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')->setTarget(pht('Pull Daemon Running')));
     } else {
         $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')->setTarget(pht('Pull Daemon Not Running'))->setNote($daemon_instructions));
     }
     $task_daemon = id(new PhabricatorDaemonLogQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)->withDaemonClasses(array('PhabricatorTaskmasterDaemon'))->setLimit(1)->execute();
     if ($task_daemon) {
         $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')->setTarget(pht('Task Daemon Running')));
     } else {
         $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')->setTarget(pht('Task Daemon Not Running'))->setNote($daemon_instructions));
     }
     if ($is_cluster) {
         // Just omit this status check for now in cluster environments. We
         // could make a service call and pull it from the repository host
         // eventually.
     } else {
         if ($repository->usesLocalWorkingCopy()) {
             $local_parent = dirname($repository->getLocalPath());
             if (Filesystem::pathExists($local_parent)) {
                 $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')->setTarget(pht('Storage Directory OK'))->setNote(phutil_tag('tt', array(), $local_parent)));
             } else {
                 $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')->setTarget(pht('No Storage Directory'))->setNote(pht('Storage directory %s does not exist, or is not readable by ' . 'the webserver. Create this directory or make it readable.', phutil_tag('tt', array(), $local_parent))));
                 return $view;
             }
             $local_path = $repository->getLocalPath();
             $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_INIT);
             if ($message) {
                 switch ($message->getStatusCode()) {
                     case PhabricatorRepositoryStatusMessage::CODE_ERROR:
                         $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')->setTarget(pht('Initialization Error'))->setNote($message->getParameter('message')));
                         return $view;
                     case PhabricatorRepositoryStatusMessage::CODE_OKAY:
                         if (Filesystem::pathExists($local_path)) {
                             $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')->setTarget(pht('Working Copy OK'))->setNote(phutil_tag('tt', array(), $local_path)));
                         } else {
                             $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')->setTarget(pht('Working Copy Error'))->setNote(pht('Working copy %s has been deleted, or is not ' . 'readable by the webserver. Make this directory ' . 'readable. If it has been deleted, the daemons should ' . 'restore it automatically.', phutil_tag('tt', array(), $local_path))));
                             return $view;
                         }
                         break;
                     case PhabricatorRepositoryStatusMessage::CODE_WORKING:
                         $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green')->setTarget(pht('Initializing Working Copy'))->setNote(pht('Daemons are initializing the working copy.')));
                         return $view;
                     default:
                         $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')->setTarget(pht('Unknown Init Status'))->setNote($message->getStatusCode()));
                         return $view;
                 }
             } else {
                 $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange')->setTarget(pht('No Working Copy Yet'))->setNote(pht('Waiting for daemons to build a working copy.')));
                 return $view;
             }
         }
     }
     $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH);
     if ($message) {
         switch ($message->getStatusCode()) {
             case PhabricatorRepositoryStatusMessage::CODE_ERROR:
                 $message = $message->getParameter('message');
                 $suggestion = null;
                 if (preg_match('/Permission denied \\(publickey\\)./', $message)) {
                     $suggestion = pht('Public Key Error: This error usually indicates that the ' . 'keypair you have configured does not have permission to ' . 'access the repository.');
                 }
                 $message = phutil_escape_html_newlines($message);
                 if ($suggestion !== null) {
                     $message = array(phutil_tag('strong', array(), $suggestion), phutil_tag('br'), phutil_tag('br'), phutil_tag('em', array(), pht('Raw Error')), phutil_tag('br'), $message);
                 }
                 $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')->setTarget(pht('Update Error'))->setNote($message));
                 return $view;
             case PhabricatorRepositoryStatusMessage::CODE_OKAY:
                 $ago = PhabricatorTime::getNow() - $message->getEpoch();
                 $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')->setTarget(pht('Updates OK'))->setNote(pht('Last updated %s (%s ago).', phabricator_datetime($message->getEpoch(), $viewer), phutil_format_relative_time_detailed($ago))));
                 break;
         }
     } else {
         $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange')->setTarget(pht('Waiting For Update'))->setNote(pht('Waiting for daemons to read updates.')));
     }
     if ($repository->isImporting()) {
         $progress = queryfx_all($repository->establishConnection('r'), 'SELECT importStatus, count(*) N FROM %T WHERE repositoryID = %d
       GROUP BY importStatus', id(new PhabricatorRepositoryCommit())->getTableName(), $repository->getID());
         $done = 0;
         $total = 0;
         foreach ($progress as $row) {
             $total += $row['N'] * 4;
             $status = $row['importStatus'];
             if ($status & PhabricatorRepositoryCommit::IMPORTED_MESSAGE) {
                 $done += $row['N'];
             }
             if ($status & PhabricatorRepositoryCommit::IMPORTED_CHANGE) {
                 $done += $row['N'];
             }
             if ($status & PhabricatorRepositoryCommit::IMPORTED_OWNERS) {
                 $done += $row['N'];
             }
             if ($status & PhabricatorRepositoryCommit::IMPORTED_HERALD) {
                 $done += $row['N'];
             }
         }
         if ($total) {
             $percentage = 100 * ($done / $total);
         } else {
             $percentage = 0;
         }
         // Cap this at "99.99%", because it's confusing to users when the actual
         // fraction is "99.996%" and it rounds up to "100.00%".
         if ($percentage > 99.98999999999999) {
             $percentage = 99.98999999999999;
         }
         $percentage = sprintf('%.2f%%', $percentage);
         $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green')->setTarget(pht('Importing'))->setNote(pht('%s Complete', $percentage)));
     } else {
         $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')->setTarget(pht('Fully Imported')));
     }
     if (idx($messages, PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE)) {
         $view->addItem(id(new PHUIStatusItemView())->setIcon(PHUIStatusItemView::ICON_UP, 'indigo')->setTarget(pht('Prioritized'))->setNote(pht('This repository will be updated soon!')));
     }
     return $view;
 }
 private function buildPropertiesTable(PhabricatorRepository $repository)
 {
     $properties = array();
     $properties['Name'] = $repository->getName();
     $properties['Callsign'] = $repository->getCallsign();
     $properties['Description'] = $repository->getDetail('description');
     switch ($repository->getVersionControlSystem()) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $properties['Clone URI'] = $repository->getPublicRemoteURI();
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             $properties['Repository Root'] = $repository->getPublicRemoteURI();
             break;
     }
     $rows = array();
     foreach ($properties as $key => $value) {
         $rows[] = array(phutil_escape_html($key), phutil_escape_html($value));
     }
     $table = new AphrontTableView($rows);
     $table->setColumnClasses(array('header', 'wide'));
     $panel = new AphrontPanelView();
     $panel->setHeader('Repository Properties');
     $panel->appendChild($table);
     return $panel;
 }
Пример #12
0
 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 isCommitOnBranch(PhabricatorRepository $repo, PhabricatorRepositoryCommit $commit, ReleephBranch $releeph_branch)
 {
     switch ($repo->getVersionControlSystem()) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
             list($output) = $repo->execxLocalCommand('branch --all --no-color --contains %s', $commit->getCommitIdentifier());
             $remote_prefix = 'remotes/origin/';
             $branches = array();
             foreach (array_filter(explode("\n", $output)) as $line) {
                 $tokens = explode(' ', $line);
                 $ref = last($tokens);
                 if (strncmp($ref, $remote_prefix, strlen($remote_prefix)) === 0) {
                     $branch = substr($ref, strlen($remote_prefix));
                     $branches[$branch] = $branch;
                 }
             }
             return idx($branches, $releeph_branch->getName());
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(DiffusionRequest::newFromDictionary(array('user' => $this->getUser(), 'repository' => $repo, 'commit' => $commit->getCommitIdentifier())));
             $path_changes = $change_query->loadChanges();
             $commit_paths = mpull($path_changes, 'getPath');
             $branch_path = $releeph_branch->getName();
             $in_branch = array();
             $ex_branch = array();
             foreach ($commit_paths as $path) {
                 if (strncmp($path, $branch_path, strlen($branch_path)) === 0) {
                     $in_branch[] = $path;
                 } else {
                     $ex_branch[] = $path;
                 }
             }
             if ($in_branch && $ex_branch) {
                 $error = pht('CONFUSION: commit %s in %s contains %d path change(s) that were ' . 'part of a Releeph branch, but also has %d path change(s) not ' . 'part of a Releeph branch!', $commit->getCommitIdentifier(), $repo->getCallsign(), count($in_branch), count($ex_branch));
                 phlog($error);
             }
             return !empty($in_branch);
             break;
     }
 }
 private function insertTask(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit, $data = array())
 {
     $vcs = $repository->getVersionControlSystem();
     switch ($vcs) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
             $class = 'PhabricatorRepositoryGitCommitMessageParserWorker';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             $class = 'PhabricatorRepositorySvnCommitMessageParserWorker';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $class = 'PhabricatorRepositoryMercurialCommitMessageParserWorker';
             break;
         default:
             throw new Exception("Unknown repository type '{$vcs}'!");
     }
     $task = new PhabricatorWorkerTask();
     $task->setTaskClass($class);
     $data['commitID'] = $commit->getID();
     $task->setData($data);
     $task->save();
 }
Пример #15
0
 public function getAbsoluteRepositoryPath(PhabricatorRepository $repository, DifferentialDiff $diff = null)
 {
     $base = '/';
     if ($diff && $diff->getSourceControlPath()) {
         $base = id(new PhutilURI($diff->getSourceControlPath()))->getPath();
     }
     $path = $this->getFilename();
     $path = rtrim($base, '/') . '/' . ltrim($path, '/');
     $vcs = $repository->getVersionControlSystem();
     if ($vcs == PhabricatorRepositoryType::REPOSITORY_TYPE_SVN) {
         $prefix = $repository->getDetail('remote-uri');
         $prefix = id(new PhutilURI($prefix))->getPath();
         if (!strncmp($path, $prefix, strlen($prefix))) {
             $path = substr($path, strlen($prefix));
         }
         $path = '/' . ltrim($path, '/');
     }
     return $path;
 }
 protected function buildDictForRepository(PhabricatorRepository $repository)
 {
     return array('name' => $repository->getName(), 'phid' => $repository->getPHID(), 'callsign' => $repository->getCallsign(), 'vcs' => $repository->getVersionControlSystem(), 'uri' => PhabricatorEnv::getProductionURI($repository->getURI()), 'remoteURI' => (string) $repository->getPublicRemoteURI(), 'tracking' => $repository->getDetail('tracking-enabled'), 'description' => $repository->getDetail('description'));
 }
 private function renderCloneCommand(PhabricatorRepository $repository, $uri, $serve_mode = null, $manage_uri = null)
 {
     require_celerity_resource('diffusion-icons-css');
     Javelin::initBehavior('select-on-click');
     switch ($repository->getVersionControlSystem()) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
             $command = csprintf('git clone %R', $uri);
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $command = csprintf('hg clone %R', $uri);
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             if ($repository->isHosted()) {
                 $command = csprintf('svn checkout %R %R', $uri, $repository->getCloneName());
             } else {
                 $command = csprintf('svn checkout %R', $uri);
             }
             break;
     }
     $input = javelin_tag('input', array('type' => 'text', 'value' => (string) $command, 'class' => 'diffusion-clone-uri', 'sigil' => 'select-on-click', 'readonly' => 'true'));
     $extras = array();
     if ($serve_mode) {
         if ($serve_mode === PhabricatorRepository::SERVE_READONLY) {
             $extras[] = pht('(Read Only)');
         }
     }
     if ($manage_uri) {
         if ($this->getRequest()->getUser()->isLoggedIn()) {
             $extras[] = phutil_tag('a', array('href' => $manage_uri), pht('Manage Credentials'));
         }
     }
     if ($extras) {
         $extras = phutil_implode_html(' ', $extras);
         $extras = phutil_tag('div', array('class' => 'diffusion-clone-extras'), $extras);
     }
     return array($input, $extras);
 }
 /**
  * Note this code is somewhat similar to the buildPatch method in
  * @{class:DifferentialReviewRequestMail}.
  *
  * @return @{class:AphrontRedirectResponse}
  */
 private function buildRawDiffResponse(DifferentialRevision $revision, array $changesets, array $vs_changesets, array $vs_map, PhabricatorRepository $repository = null)
 {
     assert_instances_of($changesets, 'DifferentialChangeset');
     assert_instances_of($vs_changesets, 'DifferentialChangeset');
     $viewer = $this->getRequest()->getUser();
     id(new DifferentialHunkQuery())->setViewer($viewer)->withChangesets($changesets)->needAttachToChangesets(true)->execute();
     $diff = new DifferentialDiff();
     $diff->attachChangesets($changesets);
     $raw_changes = $diff->buildChangesList();
     $changes = array();
     foreach ($raw_changes as $changedict) {
         $changes[] = ArcanistDiffChange::newFromDictionary($changedict);
     }
     $loader = id(new PhabricatorFileBundleLoader())->setViewer($viewer);
     $bundle = ArcanistBundle::newFromChanges($changes);
     $bundle->setLoadFileDataCallback(array($loader, 'loadFileData'));
     $vcs = $repository ? $repository->getVersionControlSystem() : null;
     switch ($vcs) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $raw_diff = $bundle->toGitPatch();
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
         default:
             $raw_diff = $bundle->toUnifiedDiff();
             break;
     }
     $request_uri = $this->getRequest()->getRequestURI();
     // this ends up being something like
     //   D123.diff
     // or the verbose
     //   D123.vs123.id123.whitespaceignore-all.diff
     // lame but nice to include these options
     $file_name = ltrim($request_uri->getPath(), '/') . '.';
     foreach ($request_uri->getQueryParams() as $key => $value) {
         if ($key == 'download') {
             continue;
         }
         $file_name .= $key . $value . '.';
     }
     $file_name .= 'diff';
     $file = PhabricatorFile::buildFromFileDataOrHash($raw_diff, array('name' => $file_name, 'ttl' => 60 * 60 * 24, 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE));
     $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
     $file->attachToObject($revision->getPHID());
     unset($unguarded);
     return $file->getRedirectResponse();
 }
 private function insertTask(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit, $data = array())
 {
     $vcs = $repository->getVersionControlSystem();
     switch ($vcs) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
             $class = 'PhabricatorRepositoryGitCommitMessageParserWorker';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             $class = 'PhabricatorRepositorySvnCommitMessageParserWorker';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $class = 'PhabricatorRepositoryMercurialCommitMessageParserWorker';
             break;
         default:
             throw new Exception(pht("Unknown repository type '%s'!", $vcs));
     }
     $data['commitID'] = $commit->getID();
     PhabricatorWorker::scheduleTask($class, $data);
 }
 /**
  * Note this code is somewhat similar to the buildPatch method in
  * @{class:DifferentialReviewRequestMail}.
  *
  * @return @{class:AphrontRedirectResponse}
  */
 private function buildRawDiffResponse(array $changesets, array $vs_changesets, array $vs_map, PhabricatorRepository $repository = null)
 {
     assert_instances_of($changesets, 'DifferentialChangeset');
     assert_instances_of($vs_changesets, 'DifferentialChangeset');
     $engine = new PhabricatorDifferenceEngine();
     $generated_changesets = array();
     foreach ($changesets as $changeset) {
         $changeset->attachHunks($changeset->loadHunks());
         $right = $changeset->makeNewFile();
         $choice = $changeset;
         $vs = idx($vs_map, $changeset->getID());
         if ($vs == -1) {
             $left = $right;
             $right = $changeset->makeOldFile();
         } else {
             if ($vs) {
                 $choice = $vs_changeset = $vs_changesets[$vs];
                 $vs_changeset->attachHunks($vs_changeset->loadHunks());
                 $left = $vs_changeset->makeNewFile();
             } else {
                 $left = $changeset->makeOldFile();
             }
         }
         $synthetic = $engine->generateChangesetFromFileContent($left, $right);
         if (!$synthetic->getAffectedLineCount()) {
             $filetype = $choice->getFileType();
             if ($filetype == DifferentialChangeType::FILE_TEXT || $filetype == DifferentialChangeType::FILE_SYMLINK) {
                 continue;
             }
         }
         $choice->attachHunks($synthetic->getHunks());
         $generated_changesets[] = $choice;
     }
     $diff = new DifferentialDiff();
     $diff->attachChangesets($generated_changesets);
     $diff_dict = $diff->getDiffDict();
     $changes = array();
     foreach ($diff_dict['changes'] as $changedict) {
         $changes[] = ArcanistDiffChange::newFromDictionary($changedict);
     }
     $bundle = ArcanistBundle::newFromChanges($changes);
     $bundle->setLoadFileDataCallback(array($this, 'loadFileByPHID'));
     $vcs = $repository ? $repository->getVersionControlSystem() : null;
     switch ($vcs) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $raw_diff = $bundle->toGitPatch();
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
         default:
             $raw_diff = $bundle->toUnifiedDiff();
             break;
     }
     $request_uri = $this->getRequest()->getRequestURI();
     // this ends up being something like
     //   D123.diff
     // or the verbose
     //   D123.vs123.id123.whitespaceignore-all.diff
     // lame but nice to include these options
     $file_name = ltrim($request_uri->getPath(), '/') . '.';
     foreach ($request_uri->getQueryParams() as $key => $value) {
         if ($key == 'download') {
             continue;
         }
         $file_name .= $key . $value . '.';
     }
     $file_name .= 'diff';
     $file = PhabricatorFile::buildFromFileDataOrHash($raw_diff, array('name' => $file_name));
     return id(new AphrontRedirectResponse())->setURI($file->getBestURI());
 }
 private function getRequestDirectoryPath(PhabricatorRepository $repository)
 {
     $request = $this->getRequest();
     $request_path = $request->getRequestURI()->getPath();
     $info = PhabricatorRepository::parseRepositoryServicePath($request_path, $repository->getVersionControlSystem());
     $base_path = $info['path'];
     // For Git repositories, strip an optional directory component if it
     // isn't the name of a known Git resource. This allows users to clone
     // repositories as "/diffusion/X/anything.git", for example.
     if ($repository->isGit()) {
         $known = array('info', 'git-upload-pack', 'git-receive-pack');
         foreach ($known as $key => $path) {
             $known[$key] = preg_quote($path, '@');
         }
         $known = implode('|', $known);
         if (preg_match('@^/([^/]+)/(' . $known . ')(/|$)@', $base_path)) {
             $base_path = preg_replace('@^/([^/]+)@', '', $base_path);
         }
     }
     return $base_path;
 }
Пример #22
0
 /**
  * Internal. Use @{method:newFromDictionary}, not this method.
  *
  * @param   PhabricatorRepository   Repository object.
  * @return  DiffusionRequest        New request object.
  * @task new
  */
 private static final function newFromRepository(PhabricatorRepository $repository)
 {
     $map = array(PhabricatorRepositoryType::REPOSITORY_TYPE_GIT => 'DiffusionGitRequest', PhabricatorRepositoryType::REPOSITORY_TYPE_SVN => 'DiffusionSvnRequest', PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL => 'DiffusionMercurialRequest');
     $class = idx($map, $repository->getVersionControlSystem());
     if (!$class) {
         throw new Exception(pht('Unknown version control system!'));
     }
     $object = new $class();
     $object->repository = $repository;
     return $object;
 }
 private function isReadOnlyRequest(PhabricatorRepository $repository)
 {
     $request = $this->getRequest();
     $method = $_SERVER['REQUEST_METHOD'];
     // TODO: This implementation is safe by default, but very incomplete.
     switch ($repository->getVersionControlSystem()) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
             $service = $request->getStr('service');
             $path = $this->getRequestDirectoryPath($repository);
             // NOTE: Service names are the reverse of what you might expect, as they
             // are from the point of view of the server. The main read service is
             // "git-upload-pack", and the main write service is "git-receive-pack".
             if ($method == 'GET' && $path == '/info/refs' && $service == 'git-upload-pack') {
                 return true;
             }
             if ($path == '/git-upload-pack') {
                 return true;
             }
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $cmd = $request->getStr('cmd');
             if ($cmd == 'batch') {
                 $cmds = idx($this->getMercurialArguments(), 'cmds');
                 return DiffusionMercurialWireProtocol::isReadOnlyBatchCommand($cmds);
             }
             return DiffusionMercurialWireProtocol::isReadOnlyCommand($cmd);
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             break;
     }
     return false;
 }
 private function insertTask(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit, $data = array())
 {
     $vcs = $repository->getVersionControlSystem();
     switch ($vcs) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
             $class = 'PhabricatorRepositoryGitCommitMessageParserWorker';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             $class = 'PhabricatorRepositorySvnCommitMessageParserWorker';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $class = 'PhabricatorRepositoryMercurialCommitMessageParserWorker';
             break;
         default:
             throw new Exception(pht("Unknown repository type '%s'!", $vcs));
     }
     $data['commitID'] = $commit->getID();
     // If the repository is importing for the first time, we schedule tasks
     // at IMPORT priority, which is very low. Making progress on importing a
     // new repository for the first time is less important than any other
     // daemon task.
     // If the repostitory has finished importing and we're just catching up
     // on recent commits, we schedule discovery at COMMIT priority, which is
     // slightly below the default priority.
     // Note that followup tasks and triggered tasks (like those generated by
     // Herald or Harbormaster) will queue at DEFAULT priority, so that each
     // commit tends to fully import before we start the next one. This tends
     // to give imports fairly predictable progress. See T11677 for some
     // discussion.
     if ($repository->isImporting()) {
         $task_priority = PhabricatorWorker::PRIORITY_IMPORT;
     } else {
         $task_priority = PhabricatorWorker::PRIORITY_COMMIT;
     }
     $options = array('priority' => $task_priority);
     PhabricatorWorker::scheduleTask($class, $data, $options);
 }