Skip to content

Commit d9ea7ba

Browse files
committed
feat: Add rclone progress tracking support and tests
1 parent a574156 commit d9ea7ba

File tree

5 files changed

+1036
-466
lines changed

5 files changed

+1036
-466
lines changed

src/Rclone.php

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ public static function prefix_flags(array $arr, string $prefix = 'RCLONE_') : ar
283283
$base_key = preg_replace(array_keys($replace_patterns), array_values($replace_patterns), (string) $key);
284284
$base_key = strtoupper($base_key);
285285

286-
$final_env_var_name;
286+
$final_env_var_name = '';
287287
// Check if the base_key already starts with the "RCLONE_" substring.
288288
if (str_starts_with($base_key, 'RCLONE_')) {
289289
// Case 1: base_key is 'RCLONE_SOME_FLAG'.
@@ -412,18 +412,21 @@ private function simpleRun(string $command, array $args = [], array $operation_f
412412
if ($onProgress) {
413413
// Enable rclone progress output if a callback is provided.
414414
// RCLONE_STATS forces updates at the specified interval.
415-
$env_options += [
416-
'RCLONE_STATS_ONE_LINE' => 'true',
417-
'RCLONE_PROGRESS' => 'true',
418-
'RCLONE_STATS' => '250ms', // Request progress updates every 250 milliseconds.
419-
];
415+
// These will be merged into allEnvs and prefixed.
416+
$env_options['STATS_ONE_LINE'] = 'true'; // Becomes RCLONE_STATS_ONE_LINE
417+
$env_options['PROGRESS'] = 'true'; // Becomes RCLONE_PROGRESS
418+
$env_options['STATS'] = '250ms'; // Becomes RCLONE_STATS
420419
}
421420

421+
// Build the full rclone command line arguments.
422+
$process_args = array_merge([self::getBIN(), $command], $args);
423+
422424
// Consolidate all environment variables (provider, global, custom, operation-specific).
423425
$final_envs = $this->allEnvs($env_options);
424426

425-
// Build the full rclone command line arguments.
426-
$process_args = array_merge([self::getBIN(), $command], $args);
427+
if ($onProgress) {
428+
$this->resetProgress(); // Ensure progress state is clean *before* this specific monitored run.
429+
}
427430

428431
$process = new Process($process_args, sys_get_temp_dir(), $final_envs);
429432

@@ -658,19 +661,22 @@ private function parseProgress(string $type, string $buffer) : void
658661
if ($type === Process::OUT) {
659662
// Regex for transfer stats. Made more robust for units (KiB, MiB, GiB, TiB, B) and ETA (can be '-', 'Ns', etc.).
660663
// iu modifiers: case-insensitive, unicode.
661-
$regex_base = '([\d.]+\s[KMGT]?i?B)\s*\/\s*([\d.]+\s[KMGT]?i?B),\s*(\d+)\%,\s*([\d.]+\s[KMGT]?i?B\/s),\s*ETA\s*(\S+)';
664+
// Corrected to ensure dataTotal allows for '-' or actual values
665+
$regex_base = '([\d.]+\s[KMGT]?i?B)\s*\/\s*([\d.]+\s[KMGT]?i?B|-),\s*(\d+)\%,\s*([\d.]+\s[KMGT]?i?B\/s|-),\s*ETA\s*(\S+)';
662666
$regex = '/' . $regex_base . '/iu';
663-
$regex_xfr = '/' . $regex_base . '\s*\(xfr#(\d+\/\d+)\)/iu';
667+
$regex_xfr = '/' . $regex_base . '\s*\(xfr#(\d+\/\d+)\)/iu'; // For multiple file transfers
664668

665669
$matches_xfr = [];
666670
$matches = [];
667671

668-
preg_match($regex_xfr, $buffer, $matches_xfr); // Using preg_match as we expect at most one progress line per buffer chunk.
672+
// Try matching the version with xfr count first
673+
preg_match($regex_xfr, $buffer, $matches_xfr);
669674

670675
if (isset($matches_xfr[0]) && count($matches_xfr) >= 7) {
671676
// raw, dataSent, dataTotal, sent (percentage), speed, eta, xfr_count
672677
$this->setProgressData($matches_xfr[0], $matches_xfr[1], $matches_xfr[2], (int) $matches_xfr[3], $matches_xfr[4], $matches_xfr[5], $matches_xfr[6]);
673678
} else {
679+
// Fallback to matching without xfr count (e.g., single file transfer or overall progress)
674680
preg_match($regex, $buffer, $matches);
675681
if (isset($matches[0]) && count($matches) >= 6) {
676682
// raw, dataSent, dataTotal, sent (percentage), speed, eta
@@ -685,9 +691,9 @@ private function parseProgress(string $type, string $buffer) : void
685691
*
686692
* @param string $raw The raw progress string.
687693
* @param string $dataSent Amount of data sent (e.g., "1.2 GiB").
688-
* @param string $dataTotal Total amount of data (e.g., "2.0 GiB").
694+
* @param string $dataTotal Total amount of data (e.g., "2.0 GiB", or "-" if unknown).
689695
* @param int $sentPercentage Percentage completed.
690-
* @param string $speed Current transfer speed (e.g., "10 MiB/s").
696+
* @param string $speed Current transfer speed (e.g., "10 MiB/s", or "-" if unknown).
691697
* @param string $eta Estimated time remaining (e.g., "1m2s", "-", "0s").
692698
* @param string|null $xfr Current transferring files count (e.g., "1/10"). Defaults to '1/1'.
693699
*/

0 commit comments

Comments
 (0)