Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/diffusion/conduit/DiffusionSearchQueryConduitAPIMethod.php
12242 views
1
<?php
2
3
final 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');
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
}
130
131