@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Allow searching in repositories

Summary: We may later integrate it in the global search but I want to leave it here too for the case that you want to search just some repository or some part of it.

Test Plan: Browsed repo in SVN and Git, searched in Git.

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Korvin, chad

Differential Revision: https://secure.phabricator.com/D5738

+216 -42
+215 -42
src/applications/diffusion/controller/DiffusionBrowseController.php
··· 4 4 5 5 public function processRequest() { 6 6 $drequest = $this->diffusionRequest; 7 + $is_file = false; 7 8 8 9 if ($this->getRequest()->getStr('before')) { 9 - $results = array(); 10 10 $is_file = true; 11 - } else { 11 + } else if ($this->getRequest()->getStr('grep') == '') { 12 12 $browse_query = DiffusionBrowseQuery::newFromDiffusionRequest($drequest); 13 13 $browse_query->setViewer($this->getRequest()->getUser()); 14 14 $results = $browse_query->loadPaths(); ··· 16 16 $is_file = ($reason == DiffusionBrowseQuery::REASON_IS_FILE); 17 17 } 18 18 19 + if ($is_file) { 20 + $controller = new DiffusionBrowseFileController($this->getRequest()); 21 + $controller->setDiffusionRequest($drequest); 22 + $controller->setCurrentApplication($this->getCurrentApplication()); 23 + return $this->delegateToController($controller); 24 + } 25 + 19 26 $content = array(); 20 27 21 28 if ($drequest->getTagContent()) { ··· 29 36 $content[] = $tag_view; 30 37 } 31 38 32 - if (!$results) { 39 + $content[] = $this->renderSearchForm(); 33 40 34 - if ($is_file) { 35 - $controller = new DiffusionBrowseFileController($this->getRequest()); 36 - $controller->setDiffusionRequest($drequest); 37 - $controller->setCurrentApplication($this->getCurrentApplication()); 38 - return $this->delegateToController($controller); 39 - } 41 + if ($this->getRequest()->getStr('grep') != '') { 42 + $content[] = $this->renderSearchResults(); 40 43 41 - $empty_result = new DiffusionEmptyResultView(); 42 - $empty_result->setDiffusionRequest($drequest); 43 - $empty_result->setBrowseQuery($browse_query); 44 - $empty_result->setView($this->getRequest()->getStr('view')); 45 - $content[] = $empty_result; 44 + } else { 45 + if (!$results) { 46 + $empty_result = new DiffusionEmptyResultView(); 47 + $empty_result->setDiffusionRequest($drequest); 48 + $empty_result->setBrowseQuery($browse_query); 49 + $empty_result->setView($this->getRequest()->getStr('view')); 50 + $content[] = $empty_result; 46 51 47 - } else { 52 + } else { 48 53 49 - $phids = array(); 50 - foreach ($results as $result) { 51 - $data = $result->getLastCommitData(); 52 - if ($data) { 53 - if ($data->getCommitDetail('authorPHID')) { 54 - $phids[$data->getCommitDetail('authorPHID')] = true; 54 + $phids = array(); 55 + foreach ($results as $result) { 56 + $data = $result->getLastCommitData(); 57 + if ($data) { 58 + if ($data->getCommitDetail('authorPHID')) { 59 + $phids[$data->getCommitDetail('authorPHID')] = true; 60 + } 55 61 } 56 62 } 57 - } 58 63 59 - $phids = array_keys($phids); 60 - $handles = $this->loadViewerHandles($phids); 64 + $phids = array_keys($phids); 65 + $handles = $this->loadViewerHandles($phids); 61 66 62 - $browse_table = new DiffusionBrowseTableView(); 63 - $browse_table->setDiffusionRequest($drequest); 64 - $browse_table->setHandles($handles); 65 - $browse_table->setPaths($results); 66 - $browse_table->setUser($this->getRequest()->getUser()); 67 + $browse_table = new DiffusionBrowseTableView(); 68 + $browse_table->setDiffusionRequest($drequest); 69 + $browse_table->setHandles($handles); 70 + $browse_table->setPaths($results); 71 + $browse_table->setUser($this->getRequest()->getUser()); 67 72 68 - $browse_panel = new AphrontPanelView(); 69 - $browse_panel->appendChild($browse_table); 70 - $browse_panel->setNoBackground(); 73 + $browse_panel = new AphrontPanelView(); 74 + $browse_panel->appendChild($browse_table); 75 + $browse_panel->setNoBackground(); 71 76 72 - $content[] = $browse_panel; 73 - } 77 + $content[] = $browse_panel; 78 + } 74 79 75 - $content[] = $this->buildOpenRevisions(); 80 + $content[] = $this->buildOpenRevisions(); 76 81 77 - $readme_content = $browse_query->renderReadme($results); 78 - if ($readme_content) { 79 - $readme_panel = new AphrontPanelView(); 80 - $readme_panel->setHeader('README'); 81 - $readme_panel->appendChild($readme_content); 82 + $readme_content = $browse_query->renderReadme($results); 83 + if ($readme_content) { 84 + $readme_panel = new AphrontPanelView(); 85 + $readme_panel->setHeader('README'); 86 + $readme_panel->appendChild($readme_content); 82 87 83 - $content[] = $readme_panel; 88 + $content[] = $readme_panel; 89 + } 84 90 } 85 - 86 91 87 92 $nav = $this->buildSideNav('browse', false); 88 93 $nav->appendChild($content); ··· 104 109 ), 105 110 )); 106 111 } 112 + 113 + 114 + private function renderSearchForm() { 115 + $drequest = $this->getDiffusionRequest(); 116 + $form = id(new AphrontFormView()) 117 + ->setUser($this->getRequest()->getUser()) 118 + ->setMethod('GET'); 119 + 120 + switch ($drequest->getRepository()->getVersionControlSystem()) { 121 + case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 122 + $form->appendChild(pht('Search is not available in Subversion.')); 123 + break; 124 + 125 + default: 126 + $form 127 + ->appendChild( 128 + id(new AphrontFormTextControl()) 129 + ->setLabel(pht('Search Here')) 130 + ->setName('grep') 131 + ->setValue($this->getRequest()->getStr('grep')) 132 + ->setCaption(pht('Regular expression'))) 133 + ->appendChild( 134 + id(new AphrontFormSubmitControl()) 135 + ->setValue(pht('Grep'))); 136 + break; 137 + } 138 + 139 + return $form; 140 + } 141 + 142 + private function renderSearchResults() { 143 + $drequest = $this->getDiffusionRequest(); 144 + $repository = $drequest->getRepository(); 145 + $results = array(); 146 + $no_data = pht('No results found.'); 147 + 148 + $limit = 100; 149 + $page = $this->getRequest()->getInt('page', 0); 150 + $pager = new AphrontPagerView(); 151 + $pager->setPageSize($limit); 152 + $pager->setOffset($page); 153 + $pager->setURI($this->getRequest()->getRequestURI(), 'page'); 154 + 155 + try { 156 + 157 + switch ($repository->getVersionControlSystem()) { 158 + case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 159 + $future = $repository->getLocalCommandFuture( 160 + // NOTE: --perl-regexp is available only with libpcre compiled in. 161 + 'grep --extended-regexp --null -n --no-color -e %s %s -- %s', 162 + $this->getRequest()->getStr('grep'), 163 + $drequest->getStableCommitName(), 164 + $drequest->getPath()); 165 + 166 + $binary_pattern = '/Binary file [^:]*:(.+) matches/'; 167 + $lines = new LinesOfALargeExecFuture($future); 168 + foreach ($lines as $line) { 169 + $result = null; 170 + if (preg_match('/[^:]*:(.+)\0(.+)\0(.*)/', $line, $result)) { 171 + $results[] = array_slice($result, 1); 172 + } else if (preg_match($binary_pattern, $line, $result)) { 173 + list(, $path) = $result; 174 + $results[] = array($path, null, pht('Binary file')); 175 + } else { 176 + $results[] = array(null, null, $line); 177 + } 178 + if (count($results) > $page + $limit) { 179 + break; 180 + } 181 + } 182 + unset($lines); 183 + 184 + break; 185 + 186 + case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 187 + $future = $repository->getLocalCommandFuture( 188 + 'grep --rev %s --print0 --line-number %s %s', 189 + hgsprintf('ancestors(%s)', $drequest->getStableCommitName()), 190 + $this->getRequest()->getStr('grep'), 191 + $drequest->getPath()); 192 + 193 + $lines = id(new LinesOfALargeExecFuture($future))->setDelimiter("\0"); 194 + $parts = array(); 195 + foreach ($lines as $line) { 196 + $parts[] = $line; 197 + if (count($parts) == 4) { 198 + list($path, $offset, $line, $string) = $parts; 199 + $results[] = array($path, $line, $string); 200 + if (count($results) > $page + $limit) { 201 + break; 202 + } 203 + $parts = array(); 204 + } 205 + } 206 + unset($lines); 207 + 208 + break; 209 + } 210 + 211 + } catch (CommandException $ex) { 212 + return id(new AphrontErrorView()) 213 + ->setTitle(pht('Search Error')) 214 + ->appendChild($ex->getStderr()); 215 + } 216 + 217 + $results = array_slice($results, $page); 218 + $results = $pager->sliceResults($results); 219 + 220 + require_celerity_resource('syntax-highlighting-css'); 221 + 222 + // NOTE: This can be wrong because we may find the string inside the 223 + // comment. But it's correct in most cases and highlighting the whole file 224 + // would be too expensive. 225 + $futures = array(); 226 + $engine = PhabricatorSyntaxHighlighter::newEngine(); 227 + foreach ($results as $result) { 228 + list($path, $line, $string) = $result; 229 + $futures["{$path}:{$line}"] = $engine->getHighlightFuture( 230 + $engine->getLanguageFromFilename($path), 231 + ltrim($string)); 232 + } 233 + 234 + try { 235 + Futures($futures)->limit(8)->resolveAll(); 236 + } catch (PhutilSyntaxHighlighterException $ex) { 237 + } 238 + 239 + $rows = array(); 240 + foreach ($results as $result) { 241 + list($path, $line, $string) = $result; 242 + 243 + $href = $drequest->generateURI(array( 244 + 'action' => 'browse', 245 + 'path' => $path, 246 + 'line' => $line, 247 + )); 248 + 249 + try { 250 + $string = $futures["{$path}:{$line}"]->resolve(); 251 + } catch (PhutilSyntaxHighlighterException $ex) { 252 + } 253 + 254 + $string = phutil_tag( 255 + 'pre', 256 + array('class' => 'PhabricatorMonospaced'), 257 + $string); 258 + 259 + $path = Filesystem::readablePath($path, $drequest->getPath()); 260 + 261 + $rows[] = array( 262 + phutil_tag('a', array('href' => $href), $path), 263 + $line, 264 + $string, 265 + ); 266 + } 267 + 268 + $table = id(new AphrontTableView($rows)) 269 + ->setClassName('remarkup-code') 270 + ->setHeaders(array(pht('Path'), pht('Line'), pht('String'))) 271 + ->setColumnClasses(array('', 'n', 'wide')) 272 + ->setNoDataString($no_data); 273 + 274 + return id(new AphrontPanelView()) 275 + ->setHeader(pht('Search Results')) 276 + ->appendChild($table) 277 + ->appendChild($pager); 278 + } 279 + 107 280 108 281 private function markupText($text) { 109 282 $engine = PhabricatorMarkupEngine::newDiffusionMarkupEngine();
+1
src/applications/diffusion/query/browse/DiffusionBrowseQuery.php
··· 72 72 } 73 73 74 74 final public function loadPaths() { 75 + $this->reason = null; 75 76 return $this->executeQuery(); 76 77 } 77 78