Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/scripts/symbols/import_repository_symbols.php
12241 views
1
#!/usr/bin/env php
2
<?php
3
4
$root = dirname(dirname(dirname(__FILE__)));
5
require_once $root.'/scripts/__init_script__.php';
6
7
$args = new PhutilArgumentParser($argv);
8
$args->setSynopsis(<<<EOSYNOPSIS
9
**import_repository_symbols.php** [__options__] __repository__ < symbols
10
11
Import repository symbols (symbols are read from stdin).
12
EOSYNOPSIS
13
);
14
$args->parseStandardArguments();
15
$args->parse(
16
array(
17
array(
18
'name' => 'no-purge',
19
'help' => pht(
20
'Do not clear all symbols for this repository before '.
21
'uploading new symbols. Useful for incremental updating.'),
22
),
23
array(
24
'name' => 'ignore-errors',
25
'help' => pht(
26
"If a line can't be parsed, ignore that line and ".
27
"continue instead of exiting."),
28
),
29
array(
30
'name' => 'max-transaction',
31
'param' => 'num-syms',
32
'default' => '100000',
33
'help' => pht(
34
'Maximum number of symbols that should '.
35
'be part of a single transaction.'),
36
),
37
array(
38
'name' => 'repository',
39
'wildcard' => true,
40
),
41
));
42
43
$identifiers = $args->getArg('repository');
44
if (count($identifiers) !== 1) {
45
$args->printHelpAndExit();
46
}
47
48
$identifier = head($identifiers);
49
$repository = id(new PhabricatorRepositoryQuery())
50
->setViewer(PhabricatorUser::getOmnipotentUser())
51
->withIdentifiers($identifiers)
52
->executeOne();
53
54
if (!$repository) {
55
echo tsprintf(
56
"%s\n",
57
pht('Repository "%s" does not exist.', $identifier));
58
exit(1);
59
}
60
61
if (!function_exists('posix_isatty') || posix_isatty(STDIN)) {
62
echo pht('Parsing input from stdin...'), "\n";
63
}
64
65
$input = file_get_contents('php://stdin');
66
$input = trim($input);
67
$input = explode("\n", $input);
68
69
70
function commit_symbols(
71
array $symbols,
72
PhabricatorRepository $repository,
73
$no_purge) {
74
75
echo pht('Looking up path IDs...'), "\n";
76
$path_map =
77
PhabricatorRepositoryCommitChangeParserWorker::lookupOrCreatePaths(
78
ipull($symbols, 'path'));
79
80
$symbol = new PhabricatorRepositorySymbol();
81
$conn_w = $symbol->establishConnection('w');
82
83
echo pht('Preparing queries...'), "\n";
84
$sql = array();
85
foreach ($symbols as $dict) {
86
$sql[] = qsprintf(
87
$conn_w,
88
'(%s, %s, %s, %s, %s, %d, %d)',
89
$repository->getPHID(),
90
$dict['ctxt'],
91
$dict['name'],
92
$dict['type'],
93
$dict['lang'],
94
$dict['line'],
95
$path_map[$dict['path']]);
96
}
97
98
if (!$no_purge) {
99
echo pht('Purging old symbols...'), "\n";
100
queryfx(
101
$conn_w,
102
'DELETE FROM %T WHERE repositoryPHID = %s',
103
$symbol->getTableName(),
104
$repository->getPHID());
105
}
106
107
echo pht('Loading %s symbols...', phutil_count($sql)), "\n";
108
foreach (array_chunk($sql, 128) as $chunk) {
109
queryfx(
110
$conn_w,
111
'INSERT INTO %T
112
(repositoryPHID, symbolContext, symbolName, symbolType,
113
symbolLanguage, lineNumber, pathID) VALUES %LQ',
114
$symbol->getTableName(),
115
$chunk);
116
}
117
}
118
119
function check_string_value($value, $field_name, $line_no, $max_length) {
120
if (strlen($value) > $max_length) {
121
throw new Exception(
122
pht(
123
"%s '%s' defined on line #%d is too long, ".
124
"maximum %s length is %d characters.",
125
$field_name,
126
$value,
127
$line_no,
128
$field_name,
129
$max_length));
130
}
131
132
if (!phutil_is_utf8_with_only_bmp_characters($value)) {
133
throw new Exception(
134
pht(
135
"%s '%s' defined on line #%d is not a valid ".
136
"UTF-8 string, it should contain only UTF-8 characters.",
137
$field_name,
138
$value,
139
$line_no));
140
}
141
}
142
143
$no_purge = $args->getArg('no-purge');
144
$symbols = array();
145
foreach ($input as $key => $line) {
146
try {
147
$line_no = $key + 1;
148
$matches = null;
149
$ok = preg_match(
150
'/^((?P<context>[^ ]+)? )?(?P<name>[^ ]+) (?P<type>[^ ]+) '.
151
'(?P<lang>[^ ]+) (?P<line>\d+) (?P<path>.*)$/',
152
$line,
153
$matches);
154
if (!$ok) {
155
throw new Exception(
156
pht(
157
"Line #%d of input is invalid. Expected five or six space-delimited ".
158
"fields: maybe symbol context, symbol name, symbol type, symbol ".
159
"language, line number, path. For example:\n\n%s\n\n".
160
"Actual line was:\n\n%s",
161
$line_no,
162
'idx function php 13 /path/to/some/file.php',
163
$line));
164
}
165
if (empty($matches['context'])) {
166
$matches['context'] = '';
167
}
168
$context = $matches['context'];
169
$name = $matches['name'];
170
$type = $matches['type'];
171
$lang = $matches['lang'];
172
$line_number = $matches['line'];
173
$path = $matches['path'];
174
175
check_string_value($context, pht('Symbol context'), $line_no, 128);
176
check_string_value($name, pht('Symbol name'), $line_no, 128);
177
check_string_value($type, pht('Symbol type'), $line_no, 12);
178
check_string_value($lang, pht('Symbol language'), $line_no, 32);
179
check_string_value($path, pht('Path'), $line_no, 512);
180
181
if (!strlen($path) || $path[0] != '/') {
182
throw new Exception(
183
pht(
184
"Path '%s' defined on line #%d is invalid. Paths should begin with ".
185
"'%s' and specify a path from the root of the project, like '%s'.",
186
$path,
187
$line_no,
188
'/',
189
'/src/utils/utils.php'));
190
}
191
192
$symbols[] = array(
193
'ctxt' => $context,
194
'name' => $name,
195
'type' => $type,
196
'lang' => $lang,
197
'line' => $line_number,
198
'path' => $path,
199
);
200
} catch (Exception $e) {
201
if ($args->getArg('ignore-errors')) {
202
continue;
203
} else {
204
throw $e;
205
}
206
}
207
208
if (count($symbols) >= $args->getArg('max-transaction')) {
209
try {
210
echo pht(
211
"Committing %s symbols...\n",
212
new PhutilNumber($args->getArg('max-transaction')));
213
commit_symbols($symbols, $repository, $no_purge);
214
$no_purge = true;
215
unset($symbols);
216
$symbols = array();
217
} catch (Exception $e) {
218
if ($args->getArg('ignore-errors')) {
219
continue;
220
} else {
221
throw $e;
222
}
223
}
224
}
225
}
226
227
if (count($symbols)) {
228
commit_symbols($symbols, $repository, $no_purge);
229
}
230
231
echo pht('Done.')."\n";
232
233