From 3a065d4ec5e5b776f619a6d21ad12a0b5423d0a3 Mon Sep 17 00:00:00 2001 From: insign <1113045+insign@users.noreply.github.com> Date: Sun, 8 Feb 2026 04:27:26 +0000 Subject: [PATCH] feat: Cache rclone version to improve performance - Add `version_cache` static property to `Rclone` class. - Cache the result of `version()` method to avoid redundant shell executions. - Invalidate cache when `setBIN()` is called. - Add `tests/Unit/VersionTest.php` to verify functionality. --- src/Rclone.php | 18 ++++++++++++++-- tests/Unit/VersionTest.php | 42 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 tests/Unit/VersionTest.php diff --git a/src/Rclone.php b/src/Rclone.php index bb8ca3e0..20b887ad 100644 --- a/src/Rclone.php +++ b/src/Rclone.php @@ -32,6 +32,7 @@ class Rclone private static array $flags = []; // Global rclone flags to be applied to all commands. private static array $envs = []; // Custom environment variables (usually rclone parameters). private static string $input = ''; // Input string to be passed to rclone commands (e.g., for rcat). + private static array $version_cache = []; // Cache for rclone version. private object $progress; // Object to store rclone progress information. private static array $reset = [ // Default values for resetting static properties. 'timeout' => 120, @@ -732,16 +733,26 @@ private function directTwinRun(string $command, ?string $left_path = NULL, ?stri */ public function version(bool $numeric = FALSE) : string|float { + $cacheKey = $numeric ? 'numeric' : 'string'; + if (isset(self::$version_cache[$cacheKey])) { + return self::$version_cache[$cacheKey]; + } + $cmd_output = $this->simpleRun('version'); // Executes 'rclone version'. // Parses version string like "rclone v1.2.3" preg_match_all('/rclone\sv(.+)/m', $cmd_output, $version_matches, PREG_SET_ORDER, 0); + $result = $numeric ? 0.0 : ''; + if (isset($version_matches[0][1])) { $version_string = $version_matches[0][1]; - return $numeric ? (float) $version_string : $version_string; + $result = $numeric ? (float) $version_string : $version_string; } - return $numeric ? 0.0 : ''; // Should not happen with a valid rclone installation. + + self::$version_cache[$cacheKey] = $result; + + return $result; } /** @@ -761,6 +772,9 @@ public static function getBIN() : string */ public static function setBIN(string $BIN) : void { + if (isset(self::$BIN) && self::$BIN !== $BIN) { + self::$version_cache = []; + } self::$BIN = $BIN; } diff --git a/tests/Unit/VersionTest.php b/tests/Unit/VersionTest.php new file mode 100644 index 00000000..e58effb3 --- /dev/null +++ b/tests/Unit/VersionTest.php @@ -0,0 +1,42 @@ +markTestSkipped("Rclone binary guessed at $bin but not found or not executable."); + } + } catch (\Exception $e) { + $this->markTestSkipped('Rclone binary not found: ' . $e->getMessage()); + } + } + + $local = new LocalProvider('local'); + $rclone = new Rclone($local); + + try { + $v1 = $rclone->version(); + $this->assertIsString($v1); + $this->assertMatchesRegularExpression('/^[\d.]+/', $v1); + + $v2 = $rclone->version(true); + $this->assertIsFloat($v2); + $this->assertGreaterThan(0, $v2); + } catch (\Exception $e) { + $this->markTestSkipped('Failed to run rclone version: ' . $e->getMessage()); + } + } +}