init commit
This commit is contained in:
commit
c9aa3c04e3
115
README.md
Normal file
115
README.md
Normal file
@ -0,0 +1,115 @@
|
||||
### rsyncer
|
||||
------------------
|
||||
|
||||
#### A thin rsync wrapper class for PHP without any dependencies
|
||||
|
||||
##### Requirements
|
||||
------------------
|
||||
PHP 5.6+, rsync, composer
|
||||
|
||||
##### Installation
|
||||
------------------
|
||||
- Use [Composer](https://getcomposer.org/doc/01-basic-usage.md) to install the package
|
||||
|
||||
- From project root directory execute
|
||||
|
||||
```composer install```
|
||||
|
||||
or
|
||||
|
||||
```composer require codeplayr/rsyncer```
|
||||
|
||||
- [Composer](https://getcomposer.org/doc/01-basic-usage.md) will take care of autoloading. Just include the autoloader at the top of the file
|
||||
|
||||
```require_once __DIR__ . '/vendor/autoload.php';```
|
||||
|
||||
|
||||
##### Usage
|
||||
------------------
|
||||
|
||||
See following example:
|
||||
|
||||
```php
|
||||
use \Codeplayr\Rsyncer\Option;
|
||||
use \Codeplayr\Rsyncer\SSH;
|
||||
use \Codeplayr\Rsyncer\Rsync;
|
||||
|
||||
$source = __DIR__ . '/src/';
|
||||
$destination = __DIR__ . '/backup/';
|
||||
|
||||
$date = date('Y-m-d', time());
|
||||
|
||||
//rsync options
|
||||
$option = new Option([
|
||||
Option::FILES_FROM => __DIR__ . '/rules.txt',
|
||||
Option::EXCLUDE_FROM=> __DIR__ . '/exclude-rules.txt',
|
||||
Option::LOG_FILE => __DIR__ . "/logs/{$date}.log",
|
||||
Option::ARCHIVE => false,
|
||||
Option::LINKS => true,
|
||||
Option::TIMES => true,
|
||||
Option::RECURSIVE => true,
|
||||
Option::VERBOSE => true,
|
||||
Option::COMPRESS => true,
|
||||
Option::CHECKSUM => true,
|
||||
Option::DRY_RUN => false,
|
||||
]);
|
||||
|
||||
//add additional flags
|
||||
$option->addFlag('human-readable')
|
||||
->addArgument('exclude', '/path/to/exclude')
|
||||
->addArgument('include', '*.html')
|
||||
->addArgument('include', '*.php')
|
||||
->addArgument('include', '*/')
|
||||
->addArgument('exclude', '*');
|
||||
|
||||
//optional ssh connection to remote host
|
||||
$ssh = new SSH([
|
||||
SSH::USERNAME => 'user',
|
||||
SSH::HOST => '1.2.3.4',
|
||||
SSH::PORT => 22,
|
||||
SSH::IDENTITY_FILE => '~/.ssh/id_rsa',
|
||||
]);
|
||||
|
||||
//configuration options
|
||||
$conf = [
|
||||
Rsync::SHOW_OUTPUT => true,
|
||||
];
|
||||
|
||||
$rsync = new Rsync( $option, $ssh, $conf );
|
||||
|
||||
//assemble and show Command
|
||||
echo $rsync->getCommand( $source, $destination );
|
||||
|
||||
//start syncing directories
|
||||
if( ! $rsync->sync( $source, $destination ) ){
|
||||
echo $rsync->getMessage()->toString();
|
||||
}
|
||||
```
|
||||
|
||||
Running the script generates following rsync command and options:
|
||||
|
||||
```shell
|
||||
rsync
|
||||
-ltrvzc
|
||||
--human-readable
|
||||
--files-from="/path/to/rules.txt"
|
||||
--exclude-from="/path/to/exclude-rules.txt"
|
||||
--log-file="/path/to/logs/2016-10-29.log"
|
||||
--exclude='/path/to/exclude'
|
||||
--include="*.html"
|
||||
--include="*.php"
|
||||
--include="*/"
|
||||
--exclude="*"
|
||||
-e="ssh -i ~/.ssh/id_rsa"
|
||||
user@1.2.3.4:"/path/to/src/" "/path/to/backup/"
|
||||
|
||||
```
|
||||
|
||||
##### Run Tests:
|
||||
----------
|
||||
|
||||
- All tests are inside `tests` folder.
|
||||
- Execute `composer install --dev phpunit/phpunit` to install phpunit
|
||||
- Run `phpunit` from inside the tests directory to execute testcase
|
||||
- Set `--coverage-text` option to show code coverage report in terminal
|
||||
|
||||
20
composer.json
Normal file
20
composer.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "codeplayr/rsyncer",
|
||||
"description": "Lightweight rsync wrapper without dependencies",
|
||||
"authors": [
|
||||
{
|
||||
"name": "codeplayr",
|
||||
"email": "w.baryluk@gmx.de"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Codeplayr\\Rsyncer\\": "src/"
|
||||
}
|
||||
}
|
||||
}
|
||||
45
src/Helper.php
Normal file
45
src/Helper.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
namespace Codeplayr\Rsyncer;
|
||||
|
||||
class Helper{
|
||||
|
||||
public function removeDash( $flag ){
|
||||
if( ! is_string( $flag ) || empty($flag) ){
|
||||
throw new \InvalidArgumentException('No String Value');
|
||||
}
|
||||
|
||||
if( $flag[0] == '-'){
|
||||
|
||||
if( strlen( $flag ) > 2 ){
|
||||
$left = substr($flag, 0, 2);
|
||||
$right = substr($flag, 2);
|
||||
$left = str_replace('-', '' , $left);
|
||||
$flag = $left . $right;
|
||||
}
|
||||
else if( strlen( $flag ) == 2 ){
|
||||
$flag = substr($flag, 1);
|
||||
}
|
||||
else{
|
||||
throw new \InvalidArgumentException('Invalid Flag Value');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( empty( $flag ) || $flag[0] == '-' ){
|
||||
throw new \InvalidArgumentException('Invalid Assembled Flag');
|
||||
}
|
||||
|
||||
return $flag;
|
||||
}
|
||||
|
||||
public function addDash( $flag ){
|
||||
if( ! is_string( $flag ) || empty($flag) ){
|
||||
throw new \InvalidArgumentException('No String Value');
|
||||
}
|
||||
|
||||
$flag = $this->removeDash( $flag );
|
||||
|
||||
return (strlen($flag) > 1) ? '--' . $flag : '-' . $flag;
|
||||
}
|
||||
|
||||
}
|
||||
36
src/Message.php
Normal file
36
src/Message.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
namespace Codeplayr\Rsyncer;
|
||||
|
||||
class Message{
|
||||
|
||||
const INVALID_EXECUTABLE= 'INVALID_EXECUTABLE';
|
||||
const INVALID_FROM_FILE = 'INVALID_FROM_FILE';
|
||||
const SUCCESS_EXECUTE = 'SUCCESS_EXECUTE';
|
||||
const ERROR_EXECUTE = 'ERROR_EXECUTE';
|
||||
const INVALID_SSH = 'INVALID SSH';
|
||||
|
||||
private $_templates = [
|
||||
self::INVALID_EXECUTABLE=> 'Invalid executable',
|
||||
self::INVALID_FROM_FILE => 'File in from-file option not exists',
|
||||
self::SUCCESS_EXECUTE => 'Success executing command',
|
||||
self::ERROR_EXECUTE => 'Error executing command',
|
||||
self::INVALID_SSH => 'Invalid SSH config',
|
||||
];
|
||||
|
||||
private $_stored_messages = [];
|
||||
|
||||
public function getMessage( $type ){
|
||||
return isset( $this->_templates[ $type ]) ? $this->_templates[ $type ] : '';
|
||||
}
|
||||
|
||||
public function store( $message ){
|
||||
$this->_stored_messages[] = $message;
|
||||
}
|
||||
|
||||
public function toString(){
|
||||
$m = [];
|
||||
foreach( $this->_stored_messages as $message ) $m[] = $message;
|
||||
return implode(' ' , $m);
|
||||
}
|
||||
|
||||
}
|
||||
146
src/Option.php
Normal file
146
src/Option.php
Normal file
@ -0,0 +1,146 @@
|
||||
<?php
|
||||
namespace Codeplayr\Rsyncer;
|
||||
|
||||
use \Codeplayr\Rsyncer\Helper;
|
||||
|
||||
class Option{
|
||||
|
||||
const ARCHIVE = 'archive'; //equals -rlptgoD (no -H,-A,-X)
|
||||
const RECURSIVE = 'recursive';
|
||||
const LINKS = 'links';
|
||||
const PERMS = 'perms';
|
||||
const TIMES = 'times';
|
||||
const GROUP = 'group';
|
||||
const OWNER = 'owner';
|
||||
const CHECKSUM = 'checksum';
|
||||
const HUMAN_READABLE = 'human_readable';
|
||||
const DEVICES = 'devices';
|
||||
const DRY_RUN = 'dry_run';
|
||||
const VERBOSE = 'verbose';
|
||||
const COMPRESS = 'compress';
|
||||
const PROGRESS = 'progress';
|
||||
const DELETE = 'delete';
|
||||
const FILES_FROM = 'files_from';
|
||||
const EXCLUDE_FROM = 'exclude_from';
|
||||
const LOG_FILE = 'log_file';
|
||||
|
||||
private $_flags = [];
|
||||
private $_extras = [];
|
||||
private $_helper = null;
|
||||
|
||||
private $_options_map = [
|
||||
self::ARCHIVE => 'a',
|
||||
self::RECURSIVE => 'r',
|
||||
self::LINKS => 'l',
|
||||
self::PERMS => 'p',
|
||||
self::TIMES => 't',
|
||||
self::GROUP => 'g',
|
||||
self::OWNER => 'o',
|
||||
self::CHECKSUM => 'c',
|
||||
self::HUMAN_READABLE => 'h',
|
||||
self::DEVICES => 'D',
|
||||
self::DRY_RUN => 'n',
|
||||
self::VERBOSE => 'v',
|
||||
self::COMPRESS => 'z',
|
||||
self::PROGRESS => 'progress',
|
||||
self::DELETE => 'delete',
|
||||
self::FILES_FROM => 'files-from',
|
||||
self::EXCLUDE_FROM => 'exclude-from',
|
||||
self::LOG_FILE => 'log-file',
|
||||
];
|
||||
|
||||
public function __construct( $options = [] ){
|
||||
|
||||
$this->_helper = new Helper();
|
||||
|
||||
if( ! is_array( $options ) ) return;
|
||||
|
||||
foreach( $options as $key => $val ){
|
||||
$flag = $this->_options_map[ $key ];
|
||||
if( $flag && $val === true ){
|
||||
$this->addFlag( $flag );
|
||||
}
|
||||
}
|
||||
|
||||
if( key_exists( self::FILES_FROM, $options ) ){
|
||||
$this->addArgument( $this->_options_map[ self::FILES_FROM ], $options[ self::FILES_FROM ] );
|
||||
}
|
||||
|
||||
if( key_exists( self::EXCLUDE_FROM, $options ) ){
|
||||
$this->addArgument( $this->_options_map[ self::EXCLUDE_FROM ], $options[ self::EXCLUDE_FROM] );
|
||||
}
|
||||
|
||||
if( key_exists( self::LOG_FILE, $options ) ){
|
||||
$this->addArgument( $this->_options_map[ self::LOG_FILE ], $options[ self::LOG_FILE ] );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function assemble(){
|
||||
$flags = $this->_assembleFlags();
|
||||
$opts = implode(' ', $this->_extras);
|
||||
|
||||
return trim( $flags . ' ' . $opts );
|
||||
}
|
||||
|
||||
public function addFlag( $flag ){
|
||||
if( ! is_string( $flag ) ){
|
||||
throw new \InvalidArgumentException('No String Value');
|
||||
}
|
||||
|
||||
$flag = $this->_helper->removeDash( $flag );
|
||||
|
||||
if( $flag == 'a' ) $this->_flags = array_merge( $this->_flags, ['r', 'l', 'p', 't', 'g', 'o', 'D' ] );
|
||||
else $this->_flags[] = $flag;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeFlag( $flag ){
|
||||
if( ! is_string( $flag ) ){
|
||||
throw new \InvalidArgumentException('No String Value');
|
||||
}
|
||||
|
||||
$flag = $this->_helper->removeDash( $flag );
|
||||
|
||||
$idx = array_search( $flag, $this->_flags );
|
||||
if( $idx >= 0 ){
|
||||
unset( $this->_flags[ $idx ] );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addArgument( $name, $value, $useEqualDelimiter = true ){
|
||||
if( ! is_string( $name ) ){
|
||||
throw new \InvalidArgumentException('No String Value');
|
||||
}
|
||||
|
||||
$name = $this->_helper->removeDash( $name );
|
||||
$name = $this->_helper->addDash( $name );
|
||||
|
||||
$this->_extras[] = ( ! $useEqualDelimiter )? $name . ' ' . escapeshellarg( $value )
|
||||
: $name . '=' . escapeshellarg( $value );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function _assembleFlags(){
|
||||
$unique_opts = array_unique( $this->_flags );
|
||||
|
||||
$flags_single = [];
|
||||
$flags_multi = [];
|
||||
|
||||
foreach( $unique_opts as $flag ){
|
||||
if( strlen($flag) == 1 ) $flags_single[] = $flag;
|
||||
else $flags_multi[] = '--' . $flag;
|
||||
}
|
||||
|
||||
$s = [];
|
||||
$s[] = '-' . implode('', $flags_single);
|
||||
$s[] = implode(' ', $flags_multi);
|
||||
|
||||
return implode(' ', $s);
|
||||
}
|
||||
|
||||
}
|
||||
141
src/Rsync.php
Normal file
141
src/Rsync.php
Normal file
@ -0,0 +1,141 @@
|
||||
<?php
|
||||
namespace Codeplayr\Rsyncer;
|
||||
|
||||
use \Codeplayr\Rsyncer\Option;
|
||||
use \Codeplayr\Rsyncer\Message;
|
||||
use \Codeplayr\Rsyncer\SSH;
|
||||
|
||||
class Rsync{
|
||||
|
||||
const EXECUTABLE = 'executable';
|
||||
const SHOW_OUTPUT = 'show_output';
|
||||
|
||||
private $_message = null;
|
||||
private $_valid = true;
|
||||
private $_option = null;
|
||||
private $_ssh = null;
|
||||
private $_conf = null;
|
||||
private $_helper = null;
|
||||
|
||||
public function __construct( Option $options = null, SSH $ssh = null, $conf = [], $message = null ){
|
||||
|
||||
$defaults = [
|
||||
self::EXECUTABLE => 'rsync',
|
||||
self::SHOW_OUTPUT => false,
|
||||
];
|
||||
|
||||
$this->_conf = array_merge( $defaults, $conf );
|
||||
|
||||
$this->_message = ($message instanceof Message ) ? $message : new Message();
|
||||
$this->_option = $options;
|
||||
$this->_ssh = $ssh;
|
||||
}
|
||||
|
||||
public function sync( $source, $destination ){
|
||||
$cmd = $this->getCommand( $source, $destination );
|
||||
|
||||
if( ! $this->_valid ) return false;
|
||||
|
||||
return $this->_execute( $cmd );
|
||||
}
|
||||
|
||||
public function getMessage(){
|
||||
return $this->_message;
|
||||
}
|
||||
|
||||
public function getCommand( $source, $destination ){
|
||||
if( ! isset( $this->_conf[ self::EXECUTABLE ] ) ){
|
||||
if( ! $this->_commandExists('rsync') ){
|
||||
$this->_message->store( $this->_message->getMessage(Message::INVALID_EXECUTABLE) );
|
||||
$this->_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_assembleCommand( $source, $destination );
|
||||
}
|
||||
|
||||
private function _execute( $cmd ){
|
||||
$b = true;
|
||||
|
||||
if( (bool)$this->_conf[ self::SHOW_OUTPUT ] ){
|
||||
$b = $this->_executeWithOutput( $cmd );
|
||||
}
|
||||
else{
|
||||
exec($cmd, $output, $error_val);
|
||||
if( $error_val !== 0 ) $b = false;
|
||||
}
|
||||
|
||||
if( $b ) $this->_message->store( $this->_message->getMessage( Message::SUCCESS_EXECUTE ));
|
||||
else $this->_message->store( $this->_message->getMessage( Message::ERROR_EXECUTE ));
|
||||
|
||||
return $b;
|
||||
}
|
||||
|
||||
private function _executeWithOutput( $command ){
|
||||
echo "Execute: " . $command . PHP_EOL;
|
||||
if( ($fp = popen( $command, "r" )) ){
|
||||
while( ! feof( $fp ) ){
|
||||
echo fread( $fp, 1024 );
|
||||
flush();
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private function _assembleCommand( $source, $destination ){
|
||||
|
||||
$cmd = [];
|
||||
|
||||
$cmd[] = $this->_conf[ self::EXECUTABLE ];
|
||||
|
||||
if( $this->_option ){
|
||||
$cmd[] = $this->_option->assemble();
|
||||
}
|
||||
|
||||
if( is_null( $this->_ssh ) ){
|
||||
$cmd[] = escapeshellarg($source);
|
||||
$cmd[] = escapeshellarg($destination);
|
||||
}
|
||||
else{
|
||||
$ssh_cmd = $this->_assembleSSHCommand( $source, $destination );
|
||||
if( ! $ssh_cmd ) $this->_valid = false;
|
||||
$cmd[] = $ssh_cmd;
|
||||
}
|
||||
|
||||
return implode(' ', $cmd);
|
||||
}
|
||||
|
||||
private function _assembleSSHCommand( $source, $destination ){
|
||||
$cmd = null;
|
||||
|
||||
$ssh_command = $this->_ssh->assemble();
|
||||
if( ! $ssh_command ){
|
||||
$this->_valid = false;
|
||||
$this->_message->store( $this->_message->getMessage( Message::INVALID_SSH ));
|
||||
}
|
||||
else{
|
||||
$cmd = [];
|
||||
$cmd[] = $ssh_command;
|
||||
|
||||
if( $this->_ssh->isRemoteSource() ){
|
||||
$cmd[] = $this->_ssh->getHost() . ':' . escapeshellarg($source);
|
||||
$cmd[] = escapeshellarg($destination);
|
||||
}
|
||||
else{
|
||||
$cmd[] = escapeshellarg($source);
|
||||
$cmd[] = $this->_ssh->getHost() . ':' . escapeshellarg($destination);
|
||||
}
|
||||
}
|
||||
|
||||
return is_array( $cmd ) ? implode(' ', $cmd) : null;
|
||||
}
|
||||
|
||||
private function _commandExists( $cmd ){
|
||||
$whereCmd = (substr( strtolower(PHP_OS), 0, 3) == 'win') ? 'where' : 'which';
|
||||
$val = shell_exec("$whereCmd $cmd");;
|
||||
return ( empty( $val ) ) ? false : true;
|
||||
}
|
||||
|
||||
}
|
||||
89
src/SSH.php
Normal file
89
src/SSH.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
namespace Codeplayr\Rsyncer;
|
||||
|
||||
use \Codeplayr\Rsyncer\Helper;
|
||||
|
||||
class SSH{
|
||||
|
||||
const EXECUTABLE = 'executable';
|
||||
const USERNAME = 'username';
|
||||
const HOST = 'host';
|
||||
const PORT = 'port';
|
||||
const IDENTITY_FILE = 'identity_file';
|
||||
const REMOTE_SOURCE = 'remote_source';
|
||||
|
||||
private $_options = [];
|
||||
private $_flags = [];
|
||||
private $_helper = null;
|
||||
|
||||
public function __construct( $options = [] ){
|
||||
|
||||
$this->_helper = new Helper();
|
||||
|
||||
$defaults = [
|
||||
self::EXECUTABLE => 'ssh',
|
||||
self::USERNAME => null,
|
||||
self::HOST => null,
|
||||
self::PORT => 22,
|
||||
self::IDENTITY_FILE => null,
|
||||
self::REMOTE_SOURCE => true,
|
||||
];
|
||||
|
||||
$this->_options = array_merge( $defaults, $options );
|
||||
}
|
||||
|
||||
public function assemble(){
|
||||
return $this->_assembleCommand();
|
||||
}
|
||||
|
||||
public function getHost(){
|
||||
return $this->_options[ self::USERNAME ] . '@' . $this->_options[ self::HOST ];
|
||||
}
|
||||
|
||||
public function isRemoteSource(){
|
||||
return (bool) $this->_options[ self::REMOTE_SOURCE ];
|
||||
}
|
||||
|
||||
public function addFlag( $name, $value = null ){
|
||||
$name = $this->_helper->removeDash( $name );
|
||||
$this->_flags[ $name ] = $value;
|
||||
}
|
||||
|
||||
private function _assembleCommand(){
|
||||
if( ! is_string( $this->_options[ self::USERNAME ] ) ){
|
||||
return null;
|
||||
}
|
||||
|
||||
if( ! is_string( $this->_options[ self::HOST ] ) ){
|
||||
return null;
|
||||
}
|
||||
|
||||
if( ! is_int( $this->_options[ self::PORT ] ) ){
|
||||
return null;
|
||||
}
|
||||
|
||||
if( ! is_string( $this->_options[ self::EXECUTABLE ] ) ){
|
||||
return null;
|
||||
}
|
||||
|
||||
$cmd = [];
|
||||
$cmd[] = '-e="' . $this->_options[ self::EXECUTABLE ];
|
||||
|
||||
if( $this->_options[ self::PORT ] != 22 ){
|
||||
$cmd[] = "-p {$this->_options[ self::PORT ]}";
|
||||
}
|
||||
|
||||
if( is_string( $this->_options[ self::IDENTITY_FILE ] ) ){
|
||||
$cmd[] = "-i {$this->_options[ self::IDENTITY_FILE ]}";
|
||||
}
|
||||
|
||||
foreach( $this->_flags as $name => $value ){
|
||||
$name = $this->_helper->addDash( $name );
|
||||
|
||||
$cmd[] = ( is_null( $value ) ) ? $name : $name . ' ' . $value;
|
||||
}
|
||||
|
||||
return implode(' ', $cmd ) . '"';
|
||||
}
|
||||
|
||||
}
|
||||
106
tests/RsyncTest.php
Normal file
106
tests/RsyncTest.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
use \Codeplayr\Rsyncer\Option;
|
||||
use \Codeplayr\Rsyncer\SSH;
|
||||
use \Codeplayr\Rsyncer\Rsync;
|
||||
use \Codeplayr\Rsyncer\Helper;
|
||||
|
||||
class RsyncTest extends PHPUnit_Framework_TestCase{
|
||||
|
||||
protected function setUp(){}
|
||||
|
||||
public function test_rsync_command_assembling_with_options_returns_valid_command(){
|
||||
|
||||
$source = __DIR__ . '/src/';
|
||||
$destination = __DIR__ . '/backup/';
|
||||
|
||||
$files_from = __DIR__ . '/rules.txt';
|
||||
|
||||
$option = new Option([
|
||||
Option::FILES_FROM => $files_from,
|
||||
Option::ARCHIVE => false,
|
||||
Option::LINKS => true,
|
||||
Option::TIMES => true,
|
||||
Option::RECURSIVE => true,
|
||||
Option::VERBOSE => true,
|
||||
Option::COMPRESS => true,
|
||||
Option::CHECKSUM => true,
|
||||
Option::DRY_RUN => false,
|
||||
]);
|
||||
|
||||
$identity_file = '/path/to/private/key';
|
||||
|
||||
$ssh = new SSH([
|
||||
SSH::USERNAME => 'root',
|
||||
SSH::HOST => '192.168.1.101',
|
||||
SSH::PORT => 22,
|
||||
SSH::IDENTITY_FILE => $identity_file,
|
||||
]);
|
||||
|
||||
$rsync = new Rsync( $option, $ssh );
|
||||
|
||||
$this->assertInstanceOf('\Codeplayr\Rsyncer\Rsync', $rsync);
|
||||
|
||||
$cmd = $rsync->getCommand( $source, $destination );
|
||||
|
||||
$this->assertContains('-ltrvzc', $cmd);
|
||||
$this->assertContains("--files-from=\"{$files_from}\"", $cmd);
|
||||
$this->assertContains("-e=\"ssh -i {$identity_file}\"", $cmd);
|
||||
}
|
||||
|
||||
public function test_rsync_execution_with_dryrun_returns_success(){
|
||||
$source = realpath( __DIR__ . '/../src/' );
|
||||
$destination = __DIR__;
|
||||
|
||||
function transform( $path ){
|
||||
$pos = strpos( $path, ':');
|
||||
$left = substr($path, 0, $pos);
|
||||
$right = substr($path, $pos + 1 );
|
||||
return str_replace('\\', '/', "/cygdrive/" . $left . $right);
|
||||
}
|
||||
|
||||
if(substr( strtolower(PHP_OS), 0, 3) == 'win'){
|
||||
$source = transform( $source );
|
||||
$destination = transform( $destination );
|
||||
}
|
||||
|
||||
$option = new Option([
|
||||
Option::ARCHIVE => true,
|
||||
Option::DRY_RUN => true,
|
||||
]);
|
||||
|
||||
$rsync = new Rsync( $option, null, [Rsync::SHOW_OUTPUT => true]);
|
||||
|
||||
$this->assertTrue( $rsync->sync( $source, $destination ) );
|
||||
}
|
||||
|
||||
public function test_flags_with_dash(){
|
||||
$helper = new Helper();
|
||||
$this->assertEquals('a', $helper->removeDash('-a'));
|
||||
$this->assertEquals('archive', $helper->removeDash('--archive'));
|
||||
$this->assertEquals('archive', $helper->removeDash('archive'));
|
||||
$this->assertEquals('-a', $helper->addDash('a'));
|
||||
$this->assertEquals('--archive', $helper->addDash('archive'));
|
||||
$this->assertEquals('--archive', $helper->addDash('--archive'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalid_flags_dataprovider
|
||||
*/
|
||||
public function test_invalid_flag_returns_exception( $flag ){
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
|
||||
$helper = new Helper();
|
||||
$helper->removeDash( $flag );
|
||||
$helper->addDash( $flag );
|
||||
}
|
||||
|
||||
public function invalid_flags_dataprovider() {
|
||||
return [
|
||||
[0],
|
||||
[''],
|
||||
['-'],
|
||||
['--']
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
2
tests/bootstrap.php
Normal file
2
tests/bootstrap.php
Normal file
@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__.'/../vendor/autoload.php';
|
||||
13
tests/phpunit.xml
Normal file
13
tests/phpunit.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="bootstrap.php" colors="true">
|
||||
<testsuites>
|
||||
<testsuite name="Rsyncer Test Suite">
|
||||
<directory>./</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">./../src/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
Loading…
Reference in New Issue
Block a user