@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<?php
2
3final class DiffusionQueryPathsConduitAPIMethod
4 extends DiffusionQueryConduitAPIMethod {
5
6 public function getAPIMethodName() {
7 return 'diffusion.querypaths';
8 }
9
10 public function getMethodDescription() {
11 return pht('Filename search on a repository.');
12 }
13
14 protected function defineReturnType() {
15 return 'list<string>';
16 }
17
18 protected function defineCustomParamTypes() {
19 return array(
20 'path' => 'required string',
21 'commit' => 'required string',
22 'pattern' => 'optional string',
23 'limit' => 'optional int',
24 'offset' => 'optional int',
25 );
26 }
27
28 protected function getResult(ConduitAPIRequest $request) {
29 $results = parent::getResult($request);
30 $offset = $request->getValue('offset', 0);
31 return array_slice($results, $offset);
32 }
33
34 protected function getGitResult(ConduitAPIRequest $request) {
35 $drequest = $this->getDiffusionRequest();
36 $path = $drequest->getPath();
37 $commit = $request->getValue('commit');
38 $repository = $drequest->getRepository();
39
40 // Recent versions of Git don't work if you pass the empty string, and
41 // require "." to list everything.
42 if (!strlen($path)) {
43 $path = '.';
44 }
45
46 $future = $repository->getLocalCommandFuture(
47 'ls-tree --name-only -r -z %s -- %s',
48 gitsprintf('%s', $commit),
49 $path);
50
51 $lines = id(new LinesOfALargeExecFuture($future))->setDelimiter("\0");
52 return $this->filterResults($lines, $request);
53 }
54
55 protected function getMercurialResult(ConduitAPIRequest $request) {
56 $drequest = $this->getDiffusionRequest();
57 $repository = $drequest->getRepository();
58 $path = $request->getValue('path');
59 $commit = $request->getValue('commit');
60
61 $entire_manifest = id(new DiffusionLowLevelMercurialPathsQuery())
62 ->setRepository($repository)
63 ->withCommit($commit)
64 ->withPath($path)
65 ->execute();
66
67 $match_against = trim($path, '/');
68 $match_len = strlen($match_against);
69
70 $lines = array();
71 foreach ($entire_manifest as $path) {
72 if (strlen($path) && !strncmp($path, $match_against, $match_len)) {
73 $lines[] = $path;
74 }
75 }
76
77 return $this->filterResults($lines, $request);
78 }
79
80 protected function filterResults($lines, ConduitAPIRequest $request) {
81 $pattern = $request->getValue('pattern');
82 $limit = (int)$request->getValue('limit');
83 $offset = (int)$request->getValue('offset');
84
85 if (phutil_nonempty_string($pattern)) {
86 // Add delimiters to the regex pattern.
87 $pattern = '('.$pattern.')';
88 }
89
90 $results = array();
91 $count = 0;
92 foreach ($lines as $line) {
93 if (phutil_nonempty_string($pattern) && !preg_match($pattern, $line)) {
94 continue;
95 }
96
97 $results[] = $line;
98 $count++;
99
100 if ($limit && ($count >= ($offset + $limit))) {
101 break;
102 }
103 }
104
105 return $results;
106 }
107
108}