From 03ea326e88c55564244cced0a947182ea7177f4b Mon Sep 17 00:00:00 2001 From: augushong Date: Wed, 20 Sep 2023 10:14:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=9B=B4=E6=96=B0=E7=9A=84?= =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/common/command/admin/Update.php | 76 ++++++++++++++++++-- app/common/tools/PathTools.php | 77 ++++++++++++--------- composer.json | 2 +- composer.lock | 103 ++++++++++++++++------------ config/update.php | 4 ++ 5 files changed, 179 insertions(+), 83 deletions(-) diff --git a/app/common/command/admin/Update.php b/app/common/command/admin/Update.php index 2c6a0e0..197a762 100644 --- a/app/common/command/admin/Update.php +++ b/app/common/command/admin/Update.php @@ -41,7 +41,7 @@ class Update extends Command $version_file_regx = "/\bconst VERSION\s*=\s*'[\d\.a-z]+'/"; - $output->writeln('下载最新代码'); + $output->writeln('获取最新代码'); $last_version_git = new Git(); $last_version_repo = $last_version_git->cloneRepository(self::REPO, $last_version_dir); @@ -88,7 +88,7 @@ class Update extends Command // 获取当前版本要替换的文件 $current_version_filesystem = new Filesystem(new LocalFilesystemAdapter($current_version_dir)); - $current_version_list_files = $current_version_filesystem->listContents('', Filesystem::LIST_DEEP) + $current_version_list_files = $current_version_filesystem->listContents('/', Filesystem::LIST_DEEP) ->filter(function (StorageAttributes $attributes) use ($current_version_update_config) { if ($attributes->isDir()) { return false; @@ -121,6 +121,9 @@ class Update extends Command $output->writeln('对比源码是否被定制'); $now_dir = App::getRootPath(); + /** + * @var array + */ $changed_files = []; foreach ($current_version_list_files as $file_path) { @@ -128,8 +131,10 @@ class Update extends Command $current_version_file_path = $current_version_dir . '/' . $file_path; - if (!PathTools::compareFiles($now_file_path, $current_version_file_path)) { - $changed_files[] = $file_path; + $compare_result = PathTools::compareFiles($now_file_path, $current_version_file_path, true); + + if (!$compare_result || is_string($compare_result)) { + $changed_files[$file_path] = $compare_result; } } @@ -138,18 +143,77 @@ class Update extends Command if (!empty($changed_files)) { $output->warning('无法自动更新,以下文件被定制,请还原或手动升级:'); - foreach ($changed_files as $file_path) { + foreach ($changed_files as $file_path => $compare_result) { $output->warning($file_path); + + if (is_string($compare_result)) { + $output->writeln($compare_result); + } } - return; + $file_count = count($changed_files); + + $ask_result = $output->ask($input, "发现{$file_count}个文件被修改,如果您认为以上文件可以被覆盖或为检测错误,可以强制覆盖。\n是否强制继续更新?(y/n)"); + + if (!$ask_result) { + return; + } } // 获取最新版本需要跳过的文件 + + $last_version_skip_config = include $last_version_dir . '/config/update.php'; // 获取最新版本要替换的文件 + $last_version_filesystem = new Filesystem(new LocalFilesystemAdapter($last_version_dir)); + $last_version_list_files = $last_version_filesystem->listContents('/', Filesystem::LIST_DEEP) + ->filter(function (StorageAttributes $attributes) use ($last_version_skip_config) { + if ($attributes->isDir()) { + return false; + } + + $path = $attributes->path(); + + $skip_files = $last_version_skip_config['skip_files'] ?? []; + + if (in_array($path, $skip_files)) { + return false; + } + + $skip_dir = $last_version_skip_config['skip_dir'] ?? []; + $skip_dir[] = '.git'; + + foreach ($skip_dir as $dir) { + if (str_starts_with($path, $dir)) { + return false; + } + } + + return true; + }) + ->map(fn (StorageAttributes $attributes) => $attributes->path()) + ->toArray(); // 删除当前版本要替换的文件 + foreach ($current_version_list_files as $file_path) { + $now_file_path = $now_dir . '/' . $file_path; + unlink($now_file_path); + } // 将最新版本要替换的文件替换到项目代码中 + foreach ($last_version_list_files as $file_path) { + $last_file_path = $last_version_dir . '/' . $file_path; + $now_file_path = $now_dir . '/' . $file_path; + PathTools::intiDir($now_file_path); + + copy($last_file_path, $now_file_path); + } + + // 检测now的composer依赖和最新的composer依赖 + + // 分析出最新需要的但now没有的 + + // 为用户整理出要手动调整的composer命令 + + $output->writeln('更新完成'); // 更新完成 } diff --git a/app/common/tools/PathTools.php b/app/common/tools/PathTools.php index 407c347..8bbccd0 100644 --- a/app/common/tools/PathTools.php +++ b/app/common/tools/PathTools.php @@ -2,7 +2,7 @@ namespace app\common\tools; -use Diff; +use Localheinz\Diff\Differ; use think\facade\App; class PathTools @@ -105,49 +105,58 @@ class PathTools return str_replace('/', '\\', $content); } - public static function compareFiles($a, $b) + public static function compareFiles($a, $b, $return_diff = false):bool|string { - $text_mime_type = []; - $text_mime_type[] = 'text/html'; - $text_mime_type[] = 'text/plain'; - $text_mime_type[] = 'text/css'; - $text_mime_type[] = 'image/svg+xml'; - $text_mime_type[] = 'text/x-php'; - $text_mime_type[] = 'application/json'; - $text_mime_type[] = 'application/x-wine-extension-ini'; - - if (in_array(mime_content_type($a), $text_mime_type) && in_array(mime_content_type($b), $text_mime_type)) { - // 如果都是文本文件,则执行内容对比 - $diff = new Diff(file_get_contents($a), file_get_contents($b)); - $diff_content = $diff->getGroupedOpcodes(); - - if (!empty($diff_content)) { - return false; - } else { - return true; - } - } + $result = true; // Check if filesize is different if (filesize($a) !== filesize($b)) { - return false; + $result = false; } - // Check if content is different - $ah = fopen($a, 'rb'); - $bh = fopen($b, 'rb'); + if ($result) { + // Check if content is different + $ah = fopen($a, 'rb'); + $bh = fopen($b, 'rb'); - $result = true; - while (!feof($ah)) { - if (fread($ah, 8192) != fread($bh, 8192)) { - $result = false; - break; + while (!feof($ah)) { + if (fread($ah, 8192) != fread($bh, 8192)) { + $result = false; + break; + } + } + + fclose($ah); + fclose($bh); + } + + if (!$result) { + // 如果前面的方法认为文件变化,那么以文本变化的方式识别是否变化,并给出变化的内容 + $text_mime_type = []; + $text_mime_type[] = 'text/html'; + $text_mime_type[] = 'text/plain'; + $text_mime_type[] = 'text/css'; + $text_mime_type[] = 'image/svg+xml'; + $text_mime_type[] = 'text/x-php'; + $text_mime_type[] = 'application/json'; + $text_mime_type[] = 'application/x-wine-extension-ini'; + + if (in_array(mime_content_type($a), $text_mime_type) && in_array(mime_content_type($b), $text_mime_type)) { + $a_content = file_get_contents($a); + $b_content = file_get_contents($b); + + $diff = new Differ(); + + $diff_content = $diff->diff($a_content, $b_content); + + if (!empty($diff_content)) { + $result = $return_diff ? $diff_content : false; + } else { + $result = true; + } } } - fclose($ah); - fclose($bh); - return $result; } } diff --git a/composer.json b/composer.json index 47dc92d..811149f 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,7 @@ "overtrue/flysystem-cos": "^5.0", "iidestiny/flysystem-oss": "^4.0", "czproject/git-php": "^4.2", - "phpspec/php-diff": "^1.1" + "localheinz/diff": "^1.1" }, "require-dev": { "symfony/var-dumper": "^4.2" diff --git a/composer.lock b/composer.lock index 715e82b..fe196ec 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "484d22cf717f4d930f7542ec4c37bb17", + "content-hash": "abd6c2dce1ad5e333fe3406707a11947", "packages": [ { "name": "aliyuncs/oss-sdk-php", @@ -952,6 +952,66 @@ ], "time": "2023-08-05T12:09:49+00:00" }, + { + "name": "localheinz/diff", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/localheinz/diff.git", + "reference": "851bb20ea8358c86f677f5f111c4ab031b1c764c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/localheinz/diff/zipball/851bb20ea8358c86f677f5f111c4ab031b1c764c", + "reference": "851bb20ea8358c86f677f5f111c4ab031b1c764c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Fork of sebastian/diff for use with ergebnis/composer-normalize", + "homepage": "https://github.com/localheinz/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "source": "https://github.com/localheinz/diff/tree/main" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-07-06T04:49:32+00:00" + }, { "name": "maennchen/zipstream-php", "version": "2.4.0", @@ -1508,47 +1568,6 @@ }, "time": "2023-06-14T22:48:31+00:00" }, - { - "name": "phpspec/php-diff", - "version": "v1.1.3", - "source": { - "type": "git", - "url": "https://github.com/phpspec/php-diff.git", - "reference": "fc1156187f9f6c8395886fe85ed88a0a245d72e9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/php-diff/zipball/fc1156187f9f6c8395886fe85ed88a0a245d72e9", - "reference": "fc1156187f9f6c8395886fe85ed88a0a245d72e9", - "shasum": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "Diff": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Chris Boulton", - "homepage": "http://github.com/chrisboulton" - } - ], - "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", - "support": { - "source": "https://github.com/phpspec/php-diff/tree/v1.1.3" - }, - "time": "2020-09-18T13:47:07+00:00" - }, { "name": "psr/cache", "version": "3.0.0", diff --git a/config/update.php b/config/update.php index 5516aa7..0702741 100644 --- a/config/update.php +++ b/config/update.php @@ -8,6 +8,10 @@ $skip_files[] = 'app/common/app/functions.php'; $skip_files[] = 'app/common/app/listen.php'; $skip_files[] = 'app/common/app/middleware.php'; $skip_files[] = 'app/common/app/service.php'; +$skip_files[] = 'composer.lock'; +$skip_files[] = 'README.md'; +$skip_files[] = 'README.en.md'; +$skip_files[] = 'composer.json'; $config['skip_files'] = $skip_files;