Skip to content

Commit 0c6ec87

Browse files
author
xboard
committed
refactor: rewrite restoreProtectedPlugins to use file copy instead of git
- Dockerfile: backup plugins/ to /opt/default-plugins/ at build time - Replace exec/git-based restore with pure PHP File::copyDirectory() - Only restore plugins defined in Plugin::PROTECTED_PLUGINS - Delete target directory before copy to prevent stale files - Remove function_exists('exec') guard (no longer needed)
1 parent 1e06958 commit 0c6ec87

File tree

2 files changed

+23
-54
lines changed

2 files changed

+23
-54
lines changed

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ COPY .docker/supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
3232

3333
RUN composer install --no-cache --no-dev \
3434
&& php artisan storage:link \
35+
&& cp -r plugins/ /opt/default-plugins/ \
3536
&& chown -R www:www /www \
3637
&& chmod -R 775 /www \
3738
&& mkdir -p /data \

app/Console/Commands/XboardInstall.php

Lines changed: 22 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,7 @@ public function handle()
160160
if (!self::registerAdmin($email, $password)) {
161161
abort(500, '管理员账号注册失败,请重试');
162162
}
163-
if (function_exists('exec')) {
164-
self::restoreProtectedPlugins($this);
165-
}
163+
self::restoreProtectedPlugins($this);
166164
$this->info('正在安装默认插件...');
167165
PluginManager::installDefaultPlugins();
168166
$this->info('默认插件安装完成');
@@ -369,61 +367,31 @@ private function configurePostgresql(): array
369367

370368
/**
371369
* 还原内置受保护插件(可在安装和更新时调用)
370+
* Docker 部署时 plugins/ 目录被外部挂载覆盖,需要从镜像备份中还原默认插件
372371
*/
373372
public static function restoreProtectedPlugins(Command $console = null)
374373
{
375-
exec("git config core.filemode false", $output, $returnVar);
376-
$cmd = "git status --porcelain plugins/ 2>/dev/null";
377-
exec($cmd, $output, $returnVar);
378-
if (!empty($output)) {
379-
$hasNonNewFiles = false;
380-
foreach ($output as $line) {
381-
$status = trim(substr($line, 0, 2));
382-
if ($status !== 'A') {
383-
$hasNonNewFiles = true;
384-
break;
385-
}
386-
}
387-
if ($hasNonNewFiles) {
388-
if ($console)
389-
$console->info("检测到 plugins 目录有变更,正在还原...");
390-
391-
foreach ($output as $line) {
392-
$status = trim(substr($line, 0, 2));
393-
$filePath = trim(substr($line, 3));
394-
395-
if (strpos($filePath, 'plugins/') === 0 && $status !== 'A') {
396-
$relativePath = substr($filePath, 8);
397-
if ($console) {
398-
$action = match ($status) {
399-
'M' => '修改',
400-
'D' => '删除',
401-
'R' => '重命名',
402-
'C' => '复制',
403-
default => '变更'
404-
};
405-
$console->info("还原插件文件 [{$relativePath}] ({$action})");
406-
}
407-
408-
$cmd = "git checkout HEAD -- {$filePath}";
409-
exec($cmd, $gitOutput, $gitReturnVar);
410-
411-
if ($gitReturnVar === 0) {
412-
if ($console)
413-
$console->info("插件文件 [{$relativePath}] 已还原。");
414-
} else {
415-
if ($console)
416-
$console->error("插件文件 [{$relativePath}] 还原失败。");
417-
}
418-
}
419-
}
420-
} else {
421-
if ($console)
422-
$console->info("plugins 目录状态正常,无需还原。");
374+
$backupBase = '/opt/default-plugins';
375+
$pluginsBase = base_path('plugins');
376+
377+
if (!File::isDirectory($backupBase)) {
378+
$console?->info('非 Docker 环境或备份目录不存在,跳过插件还原。');
379+
return;
380+
}
381+
382+
foreach (Plugin::PROTECTED_PLUGINS as $pluginCode) {
383+
$dirName = Str::studly($pluginCode);
384+
$source = "{$backupBase}/{$dirName}";
385+
$target = "{$pluginsBase}/{$dirName}";
386+
387+
if (!File::isDirectory($source)) {
388+
continue;
423389
}
424-
} else {
425-
if ($console)
426-
$console->info("plugins 目录状态正常,无需还原。");
390+
391+
// 先清除旧文件再复制,避免重命名后残留旧文件
392+
File::deleteDirectory($target);
393+
File::copyDirectory($source, $target);
394+
$console?->info("已同步默认插件 [{$dirName}]");
427395
}
428396
}
429397
}

0 commit comments

Comments
 (0)