Remove product literal strings in "pht()", part 15
[phabricator.git] / src / applications / config / controller / PhabricatorConfigConsoleController.php
blobbd23d6dde5d198246bc14c04b88eb83395f69899
1 <?php
3 final class PhabricatorConfigConsoleController
4 extends PhabricatorConfigController {
6 public function handleRequest(AphrontRequest $request) {
7 $viewer = $request->getViewer();
9 $menu = id(new PHUIObjectItemListView())
10 ->setViewer($viewer)
11 ->setBig(true);
13 $menu->addItem(
14 id(new PHUIObjectItemView())
15 ->setHeader(pht('Settings'))
16 ->setHref($this->getApplicationURI('settings/'))
17 ->setImageIcon('fa-wrench')
18 ->setClickable(true)
19 ->addAttribute(
20 pht(
21 'Review and modify configuration settings.')));
23 $menu->addItem(
24 id(new PHUIObjectItemView())
25 ->setHeader(pht('Setup Issues'))
26 ->setHref($this->getApplicationURI('issue/'))
27 ->setImageIcon('fa-exclamation-triangle')
28 ->setClickable(true)
29 ->addAttribute(
30 pht(
31 'Show unresolved issues with setup and configuration.')));
33 $menu->addItem(
34 id(new PHUIObjectItemView())
35 ->setHeader(pht('Services'))
36 ->setHref($this->getApplicationURI('cluster/databases/'))
37 ->setImageIcon('fa-server')
38 ->setClickable(true)
39 ->addAttribute(
40 pht(
41 'View status information for databases, caches, repositories, '.
42 'and other services.')));
44 $menu->addItem(
45 id(new PHUIObjectItemView())
46 ->setHeader(pht('Extensions/Modules'))
47 ->setHref($this->getApplicationURI('module/'))
48 ->setImageIcon('fa-gear')
49 ->setClickable(true)
50 ->addAttribute(
51 pht(
52 'Show installed extensions and modules.')));
54 $crumbs = $this->buildApplicationCrumbs()
55 ->addTextCrumb(pht('Console'))
56 ->setBorder(true);
58 $box = id(new PHUIObjectBoxView())
59 ->setHeaderText(pht('Configuration'))
60 ->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
61 ->setObjectList($menu);
63 $versions = $this->newLibraryVersionTable($viewer);
64 $binary_versions = $this->newBinaryVersionTable();
66 $launcher_view = id(new PHUILauncherView())
67 ->appendChild($box)
68 ->appendChild($versions)
69 ->appendChild($binary_versions);
71 $view = id(new PHUITwoColumnView())
72 ->setFooter($launcher_view);
74 return $this->newPage()
75 ->setTitle(pht('Configuration'))
76 ->setCrumbs($crumbs)
77 ->appendChild($view);
80 public function newLibraryVersionTable() {
81 $viewer = $this->getViewer();
83 $versions = $this->loadVersions($viewer);
85 $rows = array();
86 foreach ($versions as $name => $info) {
87 $branchpoint = $info['branchpoint'];
88 if (strlen($branchpoint)) {
89 $branchpoint = substr($branchpoint, 0, 12);
90 } else {
91 $branchpoint = null;
94 $version = $info['hash'];
95 if (strlen($version)) {
96 $version = substr($version, 0, 12);
97 } else {
98 $version = pht('Unknown');
102 $epoch = $info['epoch'];
103 if ($epoch) {
104 $epoch = phabricator_date($epoch, $viewer);
105 } else {
106 $epoch = null;
109 $rows[] = array(
110 $name,
111 $version,
112 $epoch,
113 $branchpoint,
117 $table_view = id(new AphrontTableView($rows))
118 ->setHeaders(
119 array(
120 pht('Library'),
121 pht('Version'),
122 pht('Date'),
123 pht('Branchpoint'),
125 ->setColumnClasses(
126 array(
127 'pri',
128 null,
129 null,
130 'wide',
133 return id(new PHUIObjectBoxView())
134 ->setHeaderText(pht('Version Information'))
135 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
136 ->appendChild($table_view);
139 private function loadVersions(PhabricatorUser $viewer) {
140 $specs = array(
141 'phabricator',
142 'arcanist',
145 $all_libraries = PhutilBootloader::getInstance()->getAllLibraries();
146 // This puts the core libraries at the top:
147 $other_libraries = array_diff($all_libraries, $specs);
148 $specs = array_merge($specs, $other_libraries);
150 $log_futures = array();
151 $remote_futures = array();
153 foreach ($specs as $lib) {
154 $root = dirname(phutil_get_library_root($lib));
156 $log_command = csprintf(
157 'git log --format=%s -n 1 --',
158 '%H %ct');
160 $remote_command = csprintf(
161 'git remote -v');
163 $log_futures[$lib] = id(new ExecFuture('%C', $log_command))
164 ->setCWD($root);
166 $remote_futures[$lib] = id(new ExecFuture('%C', $remote_command))
167 ->setCWD($root);
170 $all_futures = array_merge($log_futures, $remote_futures);
172 id(new FutureIterator($all_futures))
173 ->resolveAll();
175 // A repository may have a bunch of remotes, but we're only going to look
176 // for remotes we host to try to figure out where this repository branched.
177 $upstream_pattern = '(github\.com/phacility/|secure\.phabricator\.com/)';
179 $upstream_futures = array();
180 $lib_upstreams = array();
181 foreach ($specs as $lib) {
182 $remote_future = $remote_futures[$lib];
184 list($err, $stdout) = $remote_future->resolve();
185 if ($err) {
186 // If this fails for whatever reason, just move on.
187 continue;
190 // These look like this, with a tab separating the first two fields:
191 // remote-name http://remote.uri/ (push)
193 $upstreams = array();
195 $remotes = phutil_split_lines($stdout, false);
196 foreach ($remotes as $remote) {
197 $remote_pattern = '/^([^\t]+)\t([^ ]+) \(([^)]+)\)\z/';
198 $matches = null;
199 if (!preg_match($remote_pattern, $remote, $matches)) {
200 continue;
203 // Remote URIs are either "push" or "fetch": we only care about "fetch"
204 // URIs.
205 $type = $matches[3];
206 if ($type != 'fetch') {
207 continue;
210 $uri = $matches[2];
211 $is_upstream = preg_match($upstream_pattern, $uri);
212 if (!$is_upstream) {
213 continue;
216 $name = $matches[1];
217 $upstreams[$name] = $name;
220 // If we have several suitable upstreams, try to pick the one named
221 // "origin", if it exists. Otherwise, just pick the first one.
222 if (isset($upstreams['origin'])) {
223 $upstream = $upstreams['origin'];
224 } else if ($upstreams) {
225 $upstream = head($upstreams);
226 } else {
227 $upstream = null;
230 if (!$upstream) {
231 continue;
234 $lib_upstreams[$lib] = $upstream;
236 $merge_base_command = csprintf(
237 'git merge-base HEAD %s/master --',
238 $upstream);
240 $root = dirname(phutil_get_library_root($lib));
242 $upstream_futures[$lib] = id(new ExecFuture('%C', $merge_base_command))
243 ->setCWD($root);
246 if ($upstream_futures) {
247 id(new FutureIterator($upstream_futures))
248 ->resolveAll();
251 $results = array();
252 foreach ($log_futures as $lib => $future) {
253 list($err, $stdout) = $future->resolve();
254 if (!$err) {
255 list($hash, $epoch) = explode(' ', $stdout);
256 } else {
257 $hash = null;
258 $epoch = null;
261 $result = array(
262 'hash' => $hash,
263 'epoch' => $epoch,
264 'upstream' => null,
265 'branchpoint' => null,
268 $upstream_future = idx($upstream_futures, $lib);
269 if ($upstream_future) {
270 list($err, $stdout) = $upstream_future->resolve();
271 if (!$err) {
272 $branchpoint = trim($stdout);
273 if (strlen($branchpoint)) {
274 // We only list a branchpoint if it differs from HEAD.
275 if ($branchpoint != $hash) {
276 $result['upstream'] = $lib_upstreams[$lib];
277 $result['branchpoint'] = trim($stdout);
283 $results[$lib] = $result;
286 return $results;
289 private function newBinaryVersionTable() {
290 $rows = array();
292 $rows[] = array(
293 'php',
294 phpversion(),
295 php_sapi_name(),
298 $binaries = PhutilBinaryAnalyzer::getAllBinaries();
299 foreach ($binaries as $binary) {
300 if (!$binary->isBinaryAvailable()) {
301 $binary_version = pht('Not Available');
302 $binary_path = null;
303 } else {
304 $binary_version = $binary->getBinaryVersion();
305 $binary_path = $binary->getBinaryPath();
308 $rows[] = array(
309 $binary->getBinaryName(),
310 $binary_version,
311 $binary_path,
315 $table_view = id(new AphrontTableView($rows))
316 ->setHeaders(
317 array(
318 pht('Binary'),
319 pht('Version'),
320 pht('Path'),
322 ->setColumnClasses(
323 array(
324 'pri',
325 null,
326 'wide',
329 return id(new PHUIObjectBoxView())
330 ->setHeaderText(pht('Other Version Information'))
331 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
332 ->appendChild($table_view);