All checks were successful
		
		
	
	ci/woodpecker/push/woodpecker Pipeline was successful
				
			
		
			
				
	
	
		
			134 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			134 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace App\Rclone;
 | 
						|
 | 
						|
use Psr\Log\LoggerAwareTrait;
 | 
						|
use Psr\Log\NullLogger;
 | 
						|
 | 
						|
use Symfony\Component\Process\Process;
 | 
						|
use Symfony\Component\Process\Exception\ProcessFailedException;
 | 
						|
 | 
						|
 | 
						|
use Exception;
 | 
						|
/**
 | 
						|
 * Wrapper for the rclone command line utility
 | 
						|
 * 
 | 
						|
 * Installation of rclone is required.
 | 
						|
 * Configuration of the mounts must be done before use.
 | 
						|
 * Tested using rclone v1.53.3-DEV
 | 
						|
 */
 | 
						|
class Rclone
 | 
						|
{
 | 
						|
    use LoggerAwareTrait;
 | 
						|
 | 
						|
    protected string $rclonePath;
 | 
						|
    /**
 | 
						|
     * Global options
 | 
						|
     * 
 | 
						|
     * @var array<string> 
 | 
						|
     */
 | 
						|
    protected array $globalOptions = [];
 | 
						|
 | 
						|
    protected string $version = "";
 | 
						|
 | 
						|
    /**
 | 
						|
     * Create a new instance
 | 
						|
     * 
 | 
						|
     * Default it looks for "rclone" on the path.
 | 
						|
     * But the path can be configured to be absolute.
 | 
						|
     * 
 | 
						|
     * @param string $rclonePath Relative or absolute path
 | 
						|
     */
 | 
						|
    function __construct(string $rclonePath = "rclone")
 | 
						|
    {
 | 
						|
        $this->rclonePath = $rclonePath;
 | 
						|
        $this->setLogger(new NullLogger);
 | 
						|
        try
 | 
						|
        {
 | 
						|
            $version = $this->exec('--version');
 | 
						|
        }
 | 
						|
        catch(ProcessFailedException $e)
 | 
						|
        {
 | 
						|
            throw new Exception("Check installation of rclone");
 | 
						|
        }
 | 
						|
 | 
						|
        $this->version = explode("\n", $version)[0];
 | 
						|
        
 | 
						|
        if (!\str_contains($this->version, 'rclone')) {
 | 
						|
            throw new Exception("Rclone not recognized");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the rclone version
 | 
						|
     * 
 | 
						|
     * @return string Version string
 | 
						|
     */
 | 
						|
    function getVersion(): string
 | 
						|
    {
 | 
						|
        return $this->version;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Calculate the size of a mount/path
 | 
						|
     * 
 | 
						|
     * @return int Size in bytes
 | 
						|
     */
 | 
						|
    function getSize(string $path): int
 | 
						|
    {
 | 
						|
        $output = $this->exec('size', ['--json', $path]);
 | 
						|
        return (int)json_decode($output)->bytes;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Copy from src to dest
 | 
						|
     * 
 | 
						|
     * @param  $src       Source mount and path
 | 
						|
     * @param  $dest      Destination mount and path
 | 
						|
     * @param  $bandwidth Bandwidth limit provided as string
 | 
						|
     * @return string     Stdout from command
 | 
						|
     */
 | 
						|
    function copy(string $src, string $dest, string $bandwidth = null): string
 | 
						|
    {   
 | 
						|
        $options = array();
 | 
						|
 | 
						|
        $options[] = $src;
 | 
						|
        $options[] = $dest;
 | 
						|
        if ($bandwidth) {
 | 
						|
            $options[] = "--bwlimit";
 | 
						|
            $options[] = $bandwidth;
 | 
						|
        }
 | 
						|
 | 
						|
        return $this->exec('copy', $options);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Execute a command on the rclone binary
 | 
						|
     * 
 | 
						|
     * @param string        $command Top level Rclone command
 | 
						|
     * @param array<String> $options Array of additional options
 | 
						|
     * 
 | 
						|
     * @return string stdout data.
 | 
						|
     */
 | 
						|
    protected function exec(string $command, array $options = array()) : string
 | 
						|
    {
 | 
						|
        $process = new Process(
 | 
						|
            array_merge(
 | 
						|
                [$this->rclonePath],
 | 
						|
                $this->globalOptions,
 | 
						|
                [$command],
 | 
						|
                $options
 | 
						|
            )
 | 
						|
        );
 | 
						|
        $this->logger->info("Execute command", [$process->getCommandLine()]);
 | 
						|
        $process->setTimeout(4*3600);
 | 
						|
        $process->run();
 | 
						|
 | 
						|
        // executes after the command finishes
 | 
						|
        if (!$process->isSuccessful()) {
 | 
						|
            $this->logger->error("Failed execution");
 | 
						|
            throw new ProcessFailedException($process);
 | 
						|
        }
 | 
						|
        $this->logger->info("Return code", [$process->getExitCode()]);
 | 
						|
        return $process->getOutput();
 | 
						|
    }
 | 
						|
} |