@@ -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