update updater

This commit is contained in:
Frank Harris 2026-06-06 12:21:56 -05:00
parent cc5f7bb90c
commit d8c66c4c49
2 changed files with 31 additions and 8 deletions

View file

@ -163,9 +163,17 @@ return [
function gsp_validate_update_settings(array $cfg)
{
$errors = [];
if (!preg_match('/^https?:\/\/[^ \t\r\n]+\.git$/i', (string)$cfg['repo_url'])
&& !preg_match('/^(?:ssh:\/\/|git@)[^ \t\r\n]+$/i', (string)$cfg['repo_url'])) {
$errors[] = 'Repository URL must be an http(s), ssh, or git@ URL.';
$repo_source = trim((string)$cfg['repo_url']);
$is_git_url = preg_match('/^https?:\/\/[^ \t\r\n]+(?:\.git)?$/i', $repo_source)
|| preg_match('/^(?:ssh:\/\/|git@)[^ \t\r\n]+$/i', $repo_source);
$is_local_path = preg_match('/^\//', $repo_source)
&& strpos($repo_source, "\0") === false
&& strpos($repo_source, '..') === false;
if (!$is_git_url && !$is_local_path) {
$errors[] = 'Repository source must be an http(s), ssh, git@ URL, or a safe absolute local path.';
}
if ($is_local_path && !is_dir($repo_source)) {
$errors[] = 'Repository local path does not exist or is not a directory: ' . $repo_source;
}
if (!preg_match('/^[A-Za-z0-9._\/-]{1,128}$/', (string)$cfg['branch'])) {
$errors[] = 'Branch/channel contains invalid characters.';
@ -1020,14 +1028,22 @@ $temp_dir = sys_get_temp_dir() . '/gsp_git_' . time() . '_' . mt_rand(1000, 9999
if (!@mkdir($temp_dir, 0750, true)) {
return ['success' => false, 'error' => 'Cannot create temporary git checkout directory.'];
}
if (!function_exists('exec')) {
gsp_rmdir_recursive($temp_dir);
return ['success' => false, 'error' => 'PHP exec() is disabled, so the updater cannot run git clone.'];
}
$out = [];
$ret = 0;
$cmd = 'git clone --depth 1 --branch ' . escapeshellarg($branch) . ' ' . escapeshellarg($repo_url) . ' ' . escapeshellarg($temp_dir) . ' 2>&1';
gsp_update_log('Starting configured git checkout from ' . $repo_url . ' branch ' . $branch);
exec($cmd, $out, $ret);
if ($ret !== 0) {
gsp_rmdir_recursive($temp_dir);
return ['success' => false, 'error' => 'git clone failed: ' . implode(' | ', array_slice($out, -20))];
$tail = implode(' | ', array_slice($out, -20));
gsp_update_log('Configured git checkout failed from ' . $repo_url . ' branch ' . $branch . ': ' . $tail);
return ['success' => false, 'error' => 'git clone failed for repository source "' . $repo_url . '" branch "' . $branch . '": ' . $tail];
}
gsp_update_log('Configured git checkout completed from ' . $repo_url . ' branch ' . $branch);
return ['success' => true, 'temp_dir' => $temp_dir, 'source_root' => $temp_dir, 'output' => implode("\n", $out)];
}
@ -2081,7 +2097,7 @@ echo "<h3>Repository Settings</h3>\n";
echo "<form method='POST'>\n";
echo "<input type='hidden' name='gsp_update_csrf' value='" . htmlspecialchars($csrf_token) . "'>\n";
echo "<table class='center'>\n";
echo "<tr><td><strong>Repository URL</strong></td><td><input type='text' name='gsp_update_repo_url' value='" . htmlspecialchars($update_cfg['repo_url'], ENT_QUOTES, 'UTF-8') . "' size='85'></td></tr>\n";
echo "<tr><td><strong>Repository URL / Path</strong></td><td><input type='text' name='gsp_update_repo_url' value='" . htmlspecialchars($update_cfg['repo_url'], ENT_QUOTES, 'UTF-8') . "' size='85'></td></tr>\n";
echo "<tr><td><strong>Branch / Channel</strong></td><td><input type='text' name='gsp_update_branch' value='" . htmlspecialchars($update_cfg['branch'], ENT_QUOTES, 'UTF-8') . "' size='40'></td></tr>\n";
echo "<tr><td><strong>Repository Root</strong></td><td><input type='text' name='gsp_update_repo_root' value='" . htmlspecialchars($update_cfg['repo_root'], ENT_QUOTES, 'UTF-8') . "' size='85'></td></tr>\n";
echo "<tr><td><strong>Panel Path</strong></td><td><input type='text' name='gsp_update_panel_path' value='" . htmlspecialchars($update_cfg['panel_path'], ENT_QUOTES, 'UTF-8') . "' size='85'></td></tr>\n";

View file

@ -22,7 +22,7 @@ The update page is intentionally simple:
The admin page stores these settings in the Panel settings table:
- `gsp_update_repo_url`
- `gsp_update_repo_url` for the repository source. This may be a Git URL or a safe absolute local repository path.
- `gsp_update_branch`
- `gsp_update_repo_root`
- `gsp_update_panel_path`
@ -30,7 +30,7 @@ The admin page stores these settings in the Panel settings table:
Defaults:
- Repository URL: `http://forge.runlevelsystems.com/dev/GSP.git`
- Repository URL / Path: `http://forge.runlevelsystems.com/dev/GSP.git`
- Branch: `Panel-unstable`
- Repository Root: `/var/www/html/GSP`
- Panel Path: `/var/www/html/GSP/Panel`
@ -48,7 +48,7 @@ Important implementation note:
2. Validate repository URL, branch, repo root, and Panel path.
3. Run preflight against the configured paths.
4. Create a backup when enabled.
5. Clone the configured repository branch into a temporary checkout.
5. Clone the configured repository source and branch into a temporary checkout.
6. Sync files into the configured root/Panel paths.
7. Preserve `Panel/includes/config.inc.php`.
8. Run module updates/post-update hooks.
@ -64,3 +64,10 @@ The old repeated SSL vhost disable buttons are not part of the primary update pa
- The updater still contains legacy GitHub release helper code that is no longer rendered by the simplified primary UI.
- Real production testing should confirm file ownership and web-server permissions on `/var/www/html/GSP`.
## Repair Notes
- The update page fatal `Call to undefined function gsp_update_settings()` means the deployed `Panel/modules/administration/panel_update.php` is missing the top-level helper or is not the current repository copy.
- `Panel/modules/update/update.php` only loads `Panel/modules/administration/panel_update.php` and calls `gsp_panel_update_section()`.
- The configured update action uses `git clone --depth 1 --branch <configured branch> <configured repository source> <temporary checkout>`.
- Clone failures are logged to `logs/update_trace.log` with the configured repository source and branch.