Skip to content

Commit 1919258

Browse files
committed
[FIX] PostgreSQL support.
1 parent ea81a70 commit 1919258

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed

bin/evo

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,167 @@ final class EvoBootstrapper
263263
}
264264
$this->out("Current: {$current}");
265265
$this->out("Latest: {$tag}");
266+
$this->updatePhpInstallerPackageBestEffort();
266267
$this->installBinary(true);
267268
}
268269

270+
private function updatePhpInstallerPackageBestEffort(): void
271+
{
272+
$composer = $this->findComposerBinary();
273+
if ($composer === null) {
274+
$this->out('PHP installer update: skipped (Composer not found).');
275+
return;
276+
}
277+
278+
$workDir = $this->findComposerWorkDir();
279+
if ($workDir === null) {
280+
$this->out('PHP installer update: skipped (unable to detect Composer working dir).');
281+
return;
282+
}
283+
284+
if (!is_writable($workDir)) {
285+
$this->out("PHP installer update: skipped (working dir not writable: {$workDir}).");
286+
return;
287+
}
288+
289+
$this->out('Updating PHP installer package via Composer...');
290+
$code = $this->runProcess(
291+
[
292+
$composer,
293+
'update',
294+
'evolution-cms/installer',
295+
'--no-interaction',
296+
'--no-ansi',
297+
'--no-progress',
298+
],
299+
$workDir,
300+
[
301+
'COMPOSER_ALLOW_SUPERUSER' => '1',
302+
]
303+
);
304+
if ($code !== 0) {
305+
$this->out("PHP installer update: failed (exit code {$code}).");
306+
return;
307+
}
308+
309+
$this->out('PHP installer update: OK');
310+
}
311+
312+
private function findComposerBinary(): ?string
313+
{
314+
$bins = ['composer', 'composer2'];
315+
$binEnv = getenv('EVO_COMPOSER_BIN') ?: '';
316+
if ($binEnv !== '') {
317+
array_unshift($bins, $binEnv);
318+
}
319+
$home = getenv('HOME') ?: '';
320+
if ($home !== '') {
321+
$bins[] = $home . '/.composer/composer';
322+
$bins[] = $home . '/.composer/vendor/bin/composer';
323+
$bins[] = $home . '/bin/composer';
324+
}
325+
326+
$re = '/Composer\\s+(?:version\\s+)?([0-9]+\\.[0-9]+\\.[0-9]+)/i';
327+
foreach ($bins as $bin) {
328+
$arg = escapeshellarg($bin);
329+
$out = $this->runCommandCaptureOutput($arg . ' -V 2>&1');
330+
if (is_string($out) && preg_match($re, $out) === 1) {
331+
return $bin;
332+
}
333+
$out = $this->runCommandCaptureOutput($arg . ' --version 2>&1');
334+
if (is_string($out) && preg_match($re, $out) === 1) {
335+
return $bin;
336+
}
337+
}
338+
339+
return null;
340+
}
341+
342+
private function findComposerWorkDir(): ?string
343+
{
344+
$candidate = $this->detectComposerRootFromVendorLayout();
345+
if ($candidate !== null) {
346+
return $candidate;
347+
}
348+
349+
// Fallback: walk up a few levels and look for a composer root with vendor metadata.
350+
$dir = $this->packageRoot;
351+
for ($i = 0; $i < 6; $i++) {
352+
if (is_file($dir . '/composer.json') && is_file($dir . '/vendor/composer/installed.json')) {
353+
return $dir;
354+
}
355+
$parent = dirname($dir);
356+
if ($parent === $dir) {
357+
break;
358+
}
359+
$dir = $parent;
360+
}
361+
362+
return null;
363+
}
364+
365+
private function detectComposerRootFromVendorLayout(): ?string
366+
{
367+
$vendorDir = dirname($this->packageRoot, 2);
368+
if (basename($vendorDir) !== 'vendor') {
369+
return null;
370+
}
371+
372+
$root = dirname($vendorDir);
373+
if (!is_file($root . '/composer.json')) {
374+
return null;
375+
}
376+
if (!is_file($vendorDir . '/composer/installed.json') && !is_file($vendorDir . '/composer/installed.php')) {
377+
return null;
378+
}
379+
380+
return $root;
381+
}
382+
383+
/**
384+
* @param array<int, string> $cmd
385+
* @param array<string, string> $env
386+
*/
387+
private function runProcess(array $cmd, ?string $cwd = null, array $env = []): int
388+
{
389+
if (function_exists('proc_open') && !$this->isFunctionDisabled('proc_open')) {
390+
$descriptors = [
391+
0 => STDIN,
392+
1 => STDOUT,
393+
2 => STDERR,
394+
];
395+
396+
$mergedEnv = array_merge($_ENV, $env);
397+
$proc = @proc_open($cmd, $descriptors, $pipes, $cwd ?: null, $mergedEnv);
398+
if (is_resource($proc)) {
399+
$code = proc_close($proc);
400+
return (int)$code;
401+
}
402+
}
403+
404+
// Fallback: execute via shell.
405+
$cmdParts = [];
406+
foreach ($cmd as $part) {
407+
$cmdParts[] = escapeshellarg($part);
408+
}
409+
$full = implode(' ', $cmdParts);
410+
$exitCode = 0;
411+
if ($cwd) {
412+
$full = 'cd ' . escapeshellarg($cwd) . ' && ' . $full;
413+
}
414+
passthru($full, $exitCode);
415+
return (int)$exitCode;
416+
}
417+
418+
private function isFunctionDisabled(string $name): bool
419+
{
420+
$disabled = (string)ini_get('disable_functions');
421+
if ($disabled === '') {
422+
return false;
423+
}
424+
return stripos($disabled, $name) !== false;
425+
}
426+
269427
private function installBinary(bool $isSelfUpdate): void
270428
{
271429
$this->assertWritableDir($this->binDir);

0 commit comments

Comments
 (0)