@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
at recaptime-dev/main 129 lines 3.7 kB view raw
1<?php 2 3final class DiffusionSearchQueryConduitAPIMethod 4 extends DiffusionQueryConduitAPIMethod { 5 6 public function getAPIMethodName() { 7 return 'diffusion.searchquery'; 8 } 9 10 public function getMethodDescription() { 11 return pht('Search (grep) a repository at a specific path and commit.'); 12 } 13 14 protected function defineReturnType() { 15 return 'array'; 16 } 17 18 protected function defineCustomParamTypes() { 19 return array( 20 'path' => 'required string', 21 'commit' => 'optional string', 22 'grep' => 'required string', 23 'limit' => 'optional int', 24 'offset' => 'optional int', 25 ); 26 } 27 28 protected function getResult(ConduitAPIRequest $request) { 29 try { 30 $results = parent::getResult($request); 31 } catch (CommandException $ex) { 32 $err = $ex->getError(); 33 34 if ($err === 1) { 35 // `git grep` and `hg grep` exit with 1 if there are no matches; 36 // assume we just didn't get any hits. 37 return array(); 38 } 39 40 throw $ex; 41 } 42 43 $offset = $request->getValue('offset', 0); 44 $results = array_slice($results, $offset); 45 46 return $results; 47 } 48 49 protected function getGitResult(ConduitAPIRequest $request) { 50 $drequest = $this->getDiffusionRequest(); 51 $path = $drequest->getPath(); 52 $grep = $request->getValue('grep'); 53 $repository = $drequest->getRepository(); 54 $limit = $request->getValue('limit'); 55 $offset = $request->getValue('offset'); 56 57 // Starting with Git 2.16.0, Git assumes passing an empty argument is 58 // an error and recommends you pass "." instead. 59 if (!strlen($path)) { 60 $path = '.'; 61 } 62 63 $results = array(); 64 $future = $repository->getLocalCommandFuture( 65 // NOTE: --perl-regexp is available only with libpcre compiled in. 66 'grep --extended-regexp --null -n --no-color -f - %s -- %s', 67 gitsprintf('%s', $drequest->getStableCommit()), 68 $path); 69 70 // NOTE: We're writing the pattern on stdin to avoid issues with UTF8 71 // being mangled by the shell. See T12807. 72 $future->write($grep); 73 74 $binary_pattern = '/Binary file [^:]*:(.+) matches/'; 75 $lines = new LinesOfALargeExecFuture($future); 76 77 foreach ($lines as $line) { 78 $result = null; 79 if (preg_match('/[^:]*:(.+)\0(.+)\0(.*)/', $line, $result)) { 80 $results[] = array_slice($result, 1); 81 } else if (preg_match($binary_pattern, $line, $result)) { 82 list(, $path) = $result; 83 $results[] = array($path, null, pht('Binary file')); 84 } else { 85 $results[] = array(null, null, $line); 86 } 87 if (count($results) >= $offset + $limit) { 88 break; 89 } 90 } 91 unset($lines); 92 93 return $results; 94 } 95 96 protected function getMercurialResult(ConduitAPIRequest $request) { 97 $drequest = $this->getDiffusionRequest(); 98 $path = $drequest->getPath(); 99 $grep = $request->getValue('grep'); 100 $repository = $drequest->getRepository(); 101 $limit = $request->getValue('limit'); 102 $offset = $request->getValue('offset'); 103 104 $results = array(); 105 $future = $repository->getLocalCommandFuture( 106 'grep --rev %s --print0 --line-number -- %s %s', 107 hgsprintf('ancestors(%s)', $drequest->getStableCommit()), 108 $grep, 109 $path); 110 111 $lines = id(new LinesOfALargeExecFuture($future))->setDelimiter("\0"); 112 $parts = array(); 113 foreach ($lines as $line) { 114 $parts[] = $line; 115 if (count($parts) == 4) { 116 list($path, $char_offset, $line, $string) = $parts; 117 $results[] = array($path, $line, $string); 118 if (count($results) >= $offset + $limit) { 119 break; 120 } 121 $parts = array(); 122 } 123 } 124 unset($lines); 125 126 return $results; 127 } 128 129}