shared/platform-tools was a git submodule. On this branch it is a plain
directory of tracked files, frozen at ea3616abae30106df283e73a3e2f9e5bb0e6ae90
— the same commit fotografia.andmore.pt pins. Contents are byte-identical to
that tree, verified blob by blob.
The submodule caused every deployment failure this site has had:
- .gitmodules named no `branch`, so the update fell back to
refs/remotes/origin/HEAD — a ref a plain server-side clone never writes.
"Atualizar submódulo" failed with "Unable to find refs/remotes/origin/HEAD
revision in submodule path".
- Its URL was http://, which the origin answers with 523.
- This install is deployed by uploading files, and a submodule is invisible
to that. The tree moved forward while shared/platform-tools stayed on the
old pin, config/functions_secrets.php died on a missing compat_secrets.php,
and the whole site — public pages included — went down.
Each of those was separately fixable. Together they mean a second repository
nobody can see from the deployment path, gating whether the first one boots. A
plain directory deploys like every other file and cannot fall out of step.
The cost is that platform-tools updates no longer arrive by bumping a pin; they
are a copy-over-and-commit. shared/platform-tools/VENDORED.md records the
upstream SHA, the procedure, and which four files differ from upstream in line
endings only (social/*.js, .css, functions_publications.php — CRLF upstream,
normalised to LF here; content otherwise identical).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
44 lines
1.1 KiB
PHP
44 lines
1.1 KiB
PHP
<?php
|
|
// Self-bootstrapping download handler. Assumed location:
|
|
// <host>/shared/platform-tools/api/backup_download.php
|
|
|
|
$repo_root = dirname(__DIR__, 3);
|
|
require_once $repo_root . '/config/db.php';
|
|
require_once $repo_root . '/config/functions.php';
|
|
require_once $repo_root . '/config/functions_backup.php';
|
|
require_sysadmin();
|
|
|
|
$filename = $_GET['file'] ?? '';
|
|
|
|
if (!backup_filename_is_safe($filename)) {
|
|
http_response_code(400);
|
|
exit('Ficheiro inválido.');
|
|
}
|
|
|
|
$dir = backup_dir();
|
|
$filepath = $dir . DIRECTORY_SEPARATOR . $filename;
|
|
$real = realpath($filepath);
|
|
|
|
if ($real === false || !str_starts_with($real, $dir . DIRECTORY_SEPARATOR)) {
|
|
http_response_code(403);
|
|
exit('Acesso negado.');
|
|
}
|
|
|
|
if (!is_file($real)) {
|
|
http_response_code(404);
|
|
exit('Ficheiro não encontrado.');
|
|
}
|
|
|
|
$size = filesize($real);
|
|
|
|
header('Content-Type: application/zip');
|
|
header('Content-Disposition: attachment; filename="' . $filename . '"');
|
|
header('Content-Length: ' . $size);
|
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
|
header('Pragma: no-cache');
|
|
|
|
if (ob_get_level()) ob_end_clean();
|
|
|
|
readfile($real);
|
|
exit;
|