diff --git a/src/applications/diffusion/controller/DiffusionHomeController.php b/src/applications/diffusion/controller/DiffusionHomeController.php index f1f0305fe..a37c58a3c 100644 --- a/src/applications/diffusion/controller/DiffusionHomeController.php +++ b/src/applications/diffusion/controller/DiffusionHomeController.php @@ -1,173 +1,208 @@ <?php final class DiffusionHomeController extends DiffusionController { 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'); } } + $branch = new PhabricatorRepositoryBranch(); + $lint_messages = queryfx_all( + $branch->establishConnection('r'), + 'SELECT b.repositoryID, b.name, COUNT(lm.id) AS n + FROM %T b + LEFT JOIN %T lm ON b.id = lm.branchID + GROUP BY b.id', + $branch->getTableName(), + PhabricatorRepository::TABLE_LINTMESSAGE); + $lint_messages = igroup($lint_messages, 'repositoryID'); + $rows = array(); + $show_lint = false; foreach ($repositories as $repository) { $id = $repository->getID(); $commit = idx($commits, $id); $size = idx(idx($summaries, $id, array()), 'size', '-'); if ($size != '-') { $size = hsprintf( '<a href="%s">%s</a>', DiffusionRequest::generateDiffusionURI(array( 'callsign' => $repository->getCallsign(), 'action' => 'history', )), number_format($size)); } + $lint_branches = ipull(idx($lint_messages, $id, array()), 'n', 'name'); + $branch = $repository->getDefaultArcanistBranch(); + + if (isset($lint_branches[$branch])) { + $show_lint = true; + } + $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, + (isset($lint_branches[$branch]) + ? $lint_branches[$branch] + : ''), $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', + 'Lint', 'Last', 'Date', 'Time', )); $table->setColumnClasses( array( 'pri', 'wide', '', 'n', 'n', + 'n', '', 'right', )); + $table->setColumnVisibility( + array( + true, + true, + true, + true, + $show_lint, + true, + true, + true, + )); $panel = new AphrontPanelView(); $panel->setHeader('Browse Repositories'); $panel->appendChild($table); $crumbs = $this->buildCrumbs(); return $this->buildStandardPageResponse( array( $crumbs, $shortcut_panel, $panel, ), array( 'title' => 'Diffusion', )); } } diff --git a/src/applications/diffusion/controller/DiffusionLastModifiedController.php b/src/applications/diffusion/controller/DiffusionLastModifiedController.php index ceb92b2d3..64ab74c2c 100644 --- a/src/applications/diffusion/controller/DiffusionLastModifiedController.php +++ b/src/applications/diffusion/controller/DiffusionLastModifiedController.php @@ -1,35 +1,35 @@ <?php final class DiffusionLastModifiedController extends DiffusionController { public function processRequest() { $drequest = $this->getDiffusionRequest(); $request = $this->getRequest(); $modified_query = DiffusionLastModifiedQuery::newFromDiffusionRequest( $drequest); list($commit, $commit_data) = $modified_query->loadLastModification(); $phids = array(); if ($commit_data) { if ($commit_data->getCommitDetail('authorPHID')) { $phids[$commit_data->getCommitDetail('authorPHID')] = true; } if ($commit_data->getCommitDetail('committerPHID')) { $phids[$commit_data->getCommitDetail('committerPHID')] = true; } } $phids = array_keys($phids); $handles = $this->loadViewerHandles($phids); $output = DiffusionBrowseTableView::renderLastModifiedColumns( - $drequest->getRepository(), + $drequest, $handles, $commit, $commit_data); return id(new AphrontAjaxResponse()) ->setContent($output); } } diff --git a/src/applications/diffusion/view/DiffusionBrowseTableView.php b/src/applications/diffusion/view/DiffusionBrowseTableView.php index 9a962bd90..56eadba0b 100644 --- a/src/applications/diffusion/view/DiffusionBrowseTableView.php +++ b/src/applications/diffusion/view/DiffusionBrowseTableView.php @@ -1,245 +1,276 @@ <?php final class DiffusionBrowseTableView extends DiffusionView { private $paths; private $handles = array(); private $user; public function setPaths(array $paths) { assert_instances_of($paths, 'DiffusionRepositoryPath'); $this->paths = $paths; return $this; } public function setHandles(array $handles) { assert_instances_of($handles, 'PhabricatorObjectHandle'); $this->handles = $handles; return $this; } public function setUser(PhabricatorUser $user) { $this->user = $user; return $this; } public static function renderLastModifiedColumns( - PhabricatorRepository $repository, + DiffusionRequest $drequest, array $handles, PhabricatorRepositoryCommit $commit = null, PhabricatorRepositoryCommitData $data = null) { assert_instances_of($handles, 'PhabricatorObjectHandle'); if ($commit) { $epoch = $commit->getEpoch(); $modified = DiffusionView::linkCommit( - $repository, + $drequest->getRepository(), $commit->getCommitIdentifier()); $date = date('M j, Y', $epoch); $time = date('g:i A', $epoch); } else { $modified = ''; $date = ''; $time = ''; } if ($data) { $author_phid = $data->getCommitDetail('authorPHID'); if ($author_phid && isset($handles[$author_phid])) { $author = $handles[$author_phid]->renderLink(); } else { $author = self::renderName($data->getAuthorName()); } $committer = $data->getCommitDetail('committer'); if ($committer) { $committer_phid = $data->getCommitDetail('committerPHID'); if ($committer_phid && isset($handles[$committer_phid])) { $committer = $handles[$committer_phid]->renderLink(); } else { $committer = self::renderName($committer); } if ($author != $committer) { $author .= '/'.$committer; } } $details = AphrontTableView::renderSingleDisplayLine( phutil_escape_html($data->getSummary())); } else { $author = ''; $details = ''; } - return array( + $return = array( 'commit' => $modified, 'date' => $date, 'time' => $time, 'author' => $author, 'details' => $details, ); + + $lint = self::loadLintMessagesCount($drequest); + if ($lint !== null) { + $return['lint'] = (string)$lint; + } + return $return; + } + + private static function loadLintMessagesCount(DiffusionRequest $drequest) { + $branch = $drequest->loadBranch(); + if (!$branch) { + return null; + } + + $like = (substr($drequest->getPath(), -1) == '/' ? 'LIKE %>' : '= %s'); + return head(queryfx_one( + $drequest->getRepository()->establishConnection('r'), + 'SELECT COUNT(*) FROM %T WHERE branchID = %d AND path '.$like, + PhabricatorRepository::TABLE_LINTMESSAGE, + $branch->getID(), + '/'.$drequest->getPath())); } public function render() { $request = $this->getDiffusionRequest(); $repository = $request->getRepository(); $base_path = trim($request->getPath(), '/'); if ($base_path) { $base_path = $base_path.'/'; } $need_pull = array(); $rows = array(); $show_edit = false; foreach ($this->paths as $path) { $dir_slash = null; $file_type = $path->getFileType(); if ($file_type == DifferentialChangeType::FILE_DIRECTORY) { $browse_text = $path->getPath().'/'; $dir_slash = '/'; $browse_link = '<strong>'.$this->linkBrowse( $base_path.$path->getPath().$dir_slash, array( 'html' => $this->renderPathIcon( 'dir', $browse_text), )).'</strong>'; } else if ($file_type == DifferentialChangeType::FILE_SUBMODULE) { $browse_text = $path->getPath().'/'; $browse_link = '<strong>'. $this->linkExternal( $path->getHash(), $path->getExternalURI(), $this->renderPathIcon( 'ext', $browse_text)). '</strong>'; } else { if ($file_type == DifferentialChangeType::FILE_SYMLINK) { $type = 'link'; } else { $type = 'file'; } $browse_text = $path->getPath(); $browse_link = $this->linkBrowse( $base_path.$path->getPath(), array( 'html' => $this->renderPathIcon($type, $browse_text), )); } $commit = $path->getLastModifiedCommit(); if ($commit) { + $drequest = clone $request; + $drequest->setPath($path->getPath().$dir_slash); $dict = self::renderLastModifiedColumns( - $repository, + $drequest, $this->handles, $commit, $path->getLastCommitData()); } else { $dict = array( + 'lint' => celerity_generate_unique_node_id(), 'commit' => celerity_generate_unique_node_id(), 'date' => celerity_generate_unique_node_id(), 'time' => celerity_generate_unique_node_id(), 'author' => celerity_generate_unique_node_id(), 'details' => celerity_generate_unique_node_id(), ); $uri = (string)$request->generateURI( array( 'action' => 'lastmodified', - 'path' => $base_path.$path->getPath(), + 'path' => $base_path.$path->getPath().$dir_slash, )); $need_pull[$uri] = $dict; foreach ($dict as $k => $uniq) { $dict[$k] = '<span id="'.$uniq.'"></span>'; } } $editor_button = ''; if ($this->user) { $editor_link = $this->user->loadEditorLink( $base_path.$path->getPath(), 1, $request->getRepository()->getCallsign()); if ($editor_link) { $show_edit = true; $editor_button = phutil_render_tag( 'a', array( 'href' => $editor_link, ), 'Edit'); } } $rows[] = array( $this->linkHistory($base_path.$path->getPath().$dir_slash), $editor_button, $browse_link, + $dict['lint'], $dict['commit'], $dict['date'], $dict['time'], $dict['author'], $dict['details'], ); } if ($need_pull) { Javelin::initBehavior('diffusion-pull-lastmodified', $need_pull); } + $branch = $this->getDiffusionRequest()->loadBranch(); + $show_lint = ($branch && $branch->getLintCommit()); + $view = new AphrontTableView($rows); $view->setHeaders( array( 'History', 'Edit', 'Path', + 'Lint', 'Modified', 'Date', 'Time', 'Author/Committer', 'Details', )); $view->setColumnClasses( array( '', '', '', + 'n', '', '', 'right', '', 'wide', )); $view->setColumnVisibility( array( true, $show_edit, true, + $show_lint, true, true, true, true, true, )); return $view->render(); } private function renderPathIcon($type, $text) { require_celerity_resource('diffusion-icons-css'); return phutil_render_tag( 'span', array( 'class' => 'diffusion-path-icon diffusion-path-icon-'.$type, ), phutil_escape_html($text)); } } diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php index c2301df0b..0512211b5 100644 --- a/src/applications/repository/storage/PhabricatorRepository.php +++ b/src/applications/repository/storage/PhabricatorRepository.php @@ -1,588 +1,592 @@ <?php /** * @task uri Repository URI Management */ final class PhabricatorRepository extends PhabricatorRepositoryDAO { const TABLE_PATH = 'repository_path'; const TABLE_PATHCHANGE = 'repository_pathchange'; const TABLE_FILESYSTEM = 'repository_filesystem'; const TABLE_SUMMARY = 'repository_summary'; const TABLE_BADCOMMIT = 'repository_badcommit'; const TABLE_LINTMESSAGE = 'repository_lintmessage'; protected $phid; protected $name; protected $callsign; protected $uuid; protected $versionControlSystem; protected $details = array(); private $sshKeyfile; public function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_SERIALIZATION => array( 'details' => self::SERIALIZATION_JSON, ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorPHIDConstants::PHID_TYPE_REPO); } public function getDetail($key, $default = null) { return idx($this->details, $key, $default); } public function setDetail($key, $value) { $this->details[$key] = $value; return $this; } public function getDiffusionBrowseURIForPath($path, $line = null, $branch = null) { $drequest = DiffusionRequest::newFromDictionary( array( 'repository' => $this, 'path' => $path, 'branch' => $branch, )); return $drequest->generateURI( array( 'action' => 'browse', 'line' => $line, )); } public function getLocalPath() { return $this->getDetail('local-path'); } public function execRemoteCommand($pattern /* , $arg, ... */) { $args = func_get_args(); $args = $this->formatRemoteCommand($args); return call_user_func_array('exec_manual', $args); } public function execxRemoteCommand($pattern /* , $arg, ... */) { $args = func_get_args(); $args = $this->formatRemoteCommand($args); return call_user_func_array('execx', $args); } public function getRemoteCommandFuture($pattern /* , $arg, ... */) { $args = func_get_args(); $args = $this->formatRemoteCommand($args); return newv('ExecFuture', $args); } public function passthruRemoteCommand($pattern /* , $arg, ... */) { $args = func_get_args(); $args = $this->formatRemoteCommand($args); return call_user_func_array('phutil_passthru', $args); } public function execLocalCommand($pattern /* , $arg, ... */) { $args = func_get_args(); $args = $this->formatLocalCommand($args); return call_user_func_array('exec_manual', $args); } public function execxLocalCommand($pattern /* , $arg, ... */) { $args = func_get_args(); $args = $this->formatLocalCommand($args); return call_user_func_array('execx', $args); } public function getLocalCommandFuture($pattern /* , $arg, ... */) { $args = func_get_args(); $args = $this->formatLocalCommand($args); return newv('ExecFuture', $args); } public function passthruLocalCommand($pattern /* , $arg, ... */) { $args = func_get_args(); $args = $this->formatLocalCommand($args); return call_user_func_array('phutil_passthru', $args); } private function formatRemoteCommand(array $args) { $pattern = $args[0]; $args = array_slice($args, 1); if ($this->shouldUseSSH()) { switch ($this->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $pattern = "SVN_SSH=%s svn --non-interactive {$pattern}"; array_unshift( $args, csprintf( 'ssh -l %s -i %s', $this->getSSHLogin(), $this->getSSHKeyfile())); break; case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $command = call_user_func_array( 'csprintf', array_merge( array( "(ssh-add %s && git {$pattern})", $this->getSSHKeyfile(), ), $args)); $pattern = "ssh-agent sh -c %s"; $args = array($command); break; case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $pattern = "hg --config ui.ssh=%s {$pattern}"; array_unshift( $args, csprintf( 'ssh -l %s -i %s', $this->getSSHLogin(), $this->getSSHKeyfile())); break; default: throw new Exception("Unrecognized version control system."); } } else if ($this->shouldUseHTTP()) { switch ($this->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $pattern = "svn ". "--non-interactive ". "--no-auth-cache ". "--trust-server-cert ". "--username %s ". "--password %s ". $pattern; array_unshift( $args, $this->getDetail('http-login'), $this->getDetail('http-pass')); break; default: throw new Exception( "No support for HTTP Basic Auth in this version control system."); } } else if ($this->shouldUseSVNProtocol()) { switch ($this->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $pattern = "svn ". "--non-interactive ". "--no-auth-cache ". "--username %s ". "--password %s ". $pattern; array_unshift( $args, $this->getDetail('http-login'), $this->getDetail('http-pass')); break; default: throw new Exception( "SVN protocol is SVN only."); } } else { switch ($this->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $pattern = "svn --non-interactive {$pattern}"; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $pattern = "git {$pattern}"; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $pattern = "hg {$pattern}"; break; default: throw new Exception("Unrecognized version control system."); } } array_unshift($args, $pattern); return $args; } private function formatLocalCommand(array $args) { $pattern = $args[0]; $args = array_slice($args, 1); switch ($this->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $pattern = "(cd %s && svn --non-interactive {$pattern})"; array_unshift($args, $this->getLocalPath()); break; case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $pattern = "(cd %s && git {$pattern})"; array_unshift($args, $this->getLocalPath()); break; case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $pattern = "(cd %s && HGPLAIN=1 hg {$pattern})"; array_unshift($args, $this->getLocalPath()); break; default: throw new Exception("Unrecognized version control system."); } array_unshift($args, $pattern); return $args; } private function getSSHLogin() { return $this->getDetail('ssh-login'); } private function getSSHKeyfile() { if ($this->sshKeyfile === null) { $key = $this->getDetail('ssh-key'); $keyfile = $this->getDetail('ssh-keyfile'); if ($keyfile) { // Make sure we can read the file, that it exists, etc. Filesystem::readFile($keyfile); $this->sshKeyfile = $keyfile; } else if ($key) { $keyfile = new TempFile('phabricator-repository-ssh-key'); chmod($keyfile, 0600); Filesystem::writeFile($keyfile, $key); $this->sshKeyfile = $keyfile; } else { $this->sshKeyfile = ''; } } return (string)$this->sshKeyfile; } public function getURI() { return '/diffusion/'.$this->getCallsign().'/'; } public function isTracked() { return $this->getDetail('tracking-enabled', false); } public function getDefaultBranch() { $default = $this->getDetail('default-branch'); if (strlen($default)) { return $default; } $default_branches = array( PhabricatorRepositoryType::REPOSITORY_TYPE_GIT => 'master', PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL => 'default', ); return idx($default_branches, $this->getVersionControlSystem()); } + public function getDefaultArcanistBranch() { + return coalesce($this->getDefaultBranch(), 'svn'); + } + private function isBranchInFilter($branch, $filter_key) { $vcs = $this->getVersionControlSystem(); $is_git = ($vcs == PhabricatorRepositoryType::REPOSITORY_TYPE_GIT); $use_filter = ($is_git); if ($use_filter) { $filter = $this->getDetail($filter_key, array()); if ($filter && empty($filter[$branch])) { return false; } } // By default, all branches pass. return true; } public function shouldTrackBranch($branch) { return $this->isBranchInFilter($branch, 'branch-filter'); } public function shouldAutocloseBranch($branch) { if ($this->getDetail('disable-autoclose', false)) { return false; } return $this->isBranchInFilter($branch, 'close-commits-filter'); } public function shouldAutocloseCommit( PhabricatorRepositoryCommit $commit, PhabricatorRepositoryCommitData $data) { if ($this->getDetail('disable-autoclose', false)) { return false; } switch ($this->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: return true; case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: break; case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: return true; default: throw new Exception("Unrecognized version control system."); } $branches = $data->getCommitDetail('seenOnBranches', array()); foreach ($branches as $branch) { if ($this->shouldAutocloseBranch($branch)) { return true; } } return false; } public function formatCommitName($commit_identifier) { $vcs = $this->getVersionControlSystem(); $type_git = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT; $type_hg = PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL; $is_git = ($vcs == $type_git); $is_hg = ($vcs == $type_hg); if ($is_git || $is_hg) { $short_identifier = substr($commit_identifier, 0, 12); } else { $short_identifier = $commit_identifier; } return 'r'.$this->getCallsign().$short_identifier; } public static function loadAllByPHIDOrCallsign(array $names) { $repositories = array(); foreach ($names as $name) { $repo = id(new PhabricatorRepository())->loadOneWhere( 'phid = %s OR callsign = %s', $name, $name); if (!$repo) { throw new Exception( "No repository with PHID or callsign '{$name}' exists!"); } $repositories[$repo->getID()] = $repo; } return $repositories; } /* -( Repository URI Management )------------------------------------------ */ /** * Get the remote URI for this repository. * * @return string * @task uri */ public function getRemoteURI() { return (string)$this->getRemoteURIObject(); } /** * Get the remote URI for this repository, without authentication information. * * @return string Repository URI. * @task uri */ public function getPublicRemoteURI() { $uri = $this->getRemoteURIObject(); // Make sure we don't leak anything if this repo is using HTTP Basic Auth // with the credentials in the URI or something zany like that. if ($uri instanceof PhutilGitURI) { $uri->setUser(null); } else { $uri->setUser(null); $uri->setPass(null); } return (string)$uri; } /** * Get the protocol for the repository's remote. * * @return string Protocol, like "ssh" or "git". * @task uri */ public function getRemoteProtocol() { $uri = $this->getRemoteURIObject(); if ($uri instanceof PhutilGitURI) { return 'ssh'; } else { return $uri->getProtocol(); } } /** * Get a parsed object representation of the repository's remote URI. This * may be a normal URI (returned as a @{class@libphutil:PhutilURI}) or a git * URI (returned as a @{class@libphutil:PhutilGitURI}). * * @return wild A @{class@libphutil:PhutilURI} or * @{class@libphutil:PhutilGitURI}. * @task uri */ private function getRemoteURIObject() { $raw_uri = $this->getDetail('remote-uri'); if (!$raw_uri) { return new PhutilURI(''); } if (!strncmp($raw_uri, '/', 1)) { return new PhutilURI('file://'.$raw_uri); } $uri = new PhutilURI($raw_uri); if ($uri->getProtocol()) { if ($this->isSSHProtocol($uri->getProtocol())) { if ($this->getSSHLogin()) { $uri->setUser($this->getSSHLogin()); } } return $uri; } $uri = new PhutilGitURI($raw_uri); if ($uri->getDomain()) { if ($this->getSSHLogin()) { $uri->setUser($this->getSSHLogin()); } return $uri; } throw new Exception("Remote URI '{$raw_uri}' could not be parsed!"); } /** * Determine if we should connect to the remote using SSH flags and * credentials. * * @return bool True to use the SSH protocol. * @task uri */ private function shouldUseSSH() { $protocol = $this->getRemoteProtocol(); if ($this->isSSHProtocol($protocol)) { return (bool)$this->getSSHKeyfile(); } else { return false; } } /** * Determine if we should connect to the remote using HTTP flags and * credentials. * * @return bool True to use the HTTP protocol. * @task uri */ private function shouldUseHTTP() { $protocol = $this->getRemoteProtocol(); if ($protocol == 'http' || $protocol == 'https') { return (bool)$this->getDetail('http-login'); } else { return false; } } /** * Determine if we should connect to the remote using SVN flags and * credentials. * * @return bool True to use the SVN protocol. * @task uri */ private function shouldUseSVNProtocol() { $protocol = $this->getRemoteProtocol(); if ($protocol == 'svn') { return (bool)$this->getDetail('http-login'); } else { return false; } } /** * Determine if a protocol is SSH or SSH-like. * * @param string A protocol string, like "http" or "ssh". * @return bool True if the protocol is SSH-like. * @task uri */ private function isSSHProtocol($protocol) { return ($protocol == 'ssh' || $protocol == 'svn+ssh'); } public function delete() { $this->openTransaction(); $paths = id(new PhabricatorOwnersPath()) ->loadAllWhere('repositoryPHID = %s', $this->getPHID()); foreach ($paths as $path) { $path->delete(); } $projects = id(new PhabricatorRepositoryArcanistProject()) ->loadAllWhere('repositoryID = %d', $this->getID()); foreach ($projects as $project) { // note each project deletes its PhabricatorRepositorySymbols $project->delete(); } $commits = id(new PhabricatorRepositoryCommit()) ->loadAllWhere('repositoryID = %d', $this->getID()); foreach ($commits as $commit) { // note PhabricatorRepositoryAuditRequests and // PhabricatorRepositoryCommitData are deleted here too. $commit->delete(); } $conn_w = $this->establishConnection('w'); queryfx( $conn_w, 'DELETE FROM %T WHERE repositoryID = %d', self::TABLE_FILESYSTEM, $this->getID()); queryfx( $conn_w, 'DELETE FROM %T WHERE repositoryID = %d', self::TABLE_PATHCHANGE, $this->getID()); queryfx( $conn_w, 'DELETE FROM %T WHERE repositoryID = %d', self::TABLE_SUMMARY, $this->getID()); $result = parent::delete(); $this->saveTransaction(); return $result; } }