/**
  * Extracts a *.sspak file referenced through the passed in $dataTransfer
  * and pushes it to the environment referenced in $dataTransfer.
  *
  * @param string $workingDir Directory for the unpacked files.
  * @param DNDataTransfer $dataTransfer
  * @param DeploynautLogFile $log
  */
 protected function dataTransferRestore($workingDir, DNDataTransfer $dataTransfer, DeploynautLogFile $log)
 {
     $environment = $dataTransfer->Environment();
     $name = $environment->getFullName();
     // Rollback cleanup.
     $self = $this;
     $cleanupFn = function () use($self, $workingDir, $environment, $log) {
         // Rebuild makes sense even if failed - maybe we can at least partly recover.
         $self->rebuild($environment, $log);
         $process = new Process(sprintf('rm -rf %s', escapeshellarg($workingDir)));
         $process->run();
     };
     // Restore database into target environment
     if (in_array($dataTransfer->Mode, array('all', 'db'))) {
         $log->write(sprintf('Restore of database to "%s" started', $name));
         $args = array('data_path' => $workingDir . DIRECTORY_SEPARATOR . 'database.sql');
         $command = $this->getCommand('data:pushdb', 'db', $environment, $args, $log);
         $command->run(function ($type, $buffer) use($log) {
             $log->write($buffer);
         });
         if (!$command->isSuccessful()) {
             $cleanupFn();
             $log->write(sprintf('Restore of database to "%s" failed: %s', $name, $command->getErrorOutput()));
             $this->extend('dataTransferFailure', $environment, $log);
             throw new RuntimeException($command->getErrorOutput());
         }
         $log->write(sprintf('Restore of database to "%s" done', $name));
     }
     // Restore assets into target environment
     if (in_array($dataTransfer->Mode, array('all', 'assets'))) {
         $log->write(sprintf('Restore of assets to "%s" started', $name));
         $args = array('data_path' => $workingDir . DIRECTORY_SEPARATOR . 'assets');
         $command = $this->getCommand('data:pushassets', 'web', $environment, $args, $log);
         $command->run(function ($type, $buffer) use($log) {
             $log->write($buffer);
         });
         if (!$command->isSuccessful()) {
             $cleanupFn();
             $log->write(sprintf('Restore of assets to "%s" failed: %s', $name, $command->getErrorOutput()));
             $this->extend('dataTransferFailure', $environment, $log);
             throw new RuntimeException($command->getErrorOutput());
         }
         $log->write(sprintf('Restore of assets to "%s" done', $name));
     }
     $log->write('Rebuilding and cleaning up');
     $cleanupFn();
 }
 /**
  * Extracts a *.sspak file referenced through the passed in $dataTransfer
  * and pushes it to the environment referenced in $dataTransfer.
  *
  * @param  DNDataTransfer    $dataTransfer
  * @param  DeploynautLogFile $log
  */
 protected function dataTransferRestore(DNDataTransfer $dataTransfer, DeploynautLogFile $log)
 {
     $environmentObj = $dataTransfer->Environment();
     $project = $environmentObj->Project();
     $projectName = $project->Name;
     $environmentName = $environmentObj->Name;
     $env = $project->getProcessEnv();
     $project = DNProject::get()->filter('Name', $projectName)->first();
     $name = $projectName . ':' . $environmentName;
     $tempPath = TEMP_FOLDER . DIRECTORY_SEPARATOR . 'deploynaut-transfer-' . $dataTransfer->ID;
     mkdir($tempPath, 0700, true);
     $self = $this;
     $cleanupFn = function () use($self, $tempPath, $name, $env, $log) {
         // Rebuild even if failed - maybe we can at least partly recover.
         $self->rebuild($name, $env, $log);
         $process = new Process('rm -rf ' . escapeshellarg($tempPath));
         $process->run();
     };
     // Extract *.sspak to a temporary location
     $log->write('Extracting *.sspak file');
     $sspakFilename = $dataTransfer->DataArchive()->ArchiveFile()->FullPath;
     $sspakCmd = sprintf('sspak extract %s %s', escapeshellarg($sspakFilename), escapeshellarg($tempPath));
     $log->write($sspakCmd);
     $process = new Process($sspakCmd);
     $process->setTimeout(3600);
     $process->run();
     if (!$process->isSuccessful()) {
         $log->write('Could not extract the *.sspak file: ' . $process->getErrorOutput());
         $cleanupFn();
         throw new RuntimeException($process->getErrorOutput());
     }
     // TODO Validate that file actually contains the desired modes
     // Restore database
     if (in_array($dataTransfer->Mode, array('all', 'db'))) {
         // Upload into target environment
         $log->write('Restore of database to "' . $name . '" started');
         $args = array('data_path' => $tempPath . DIRECTORY_SEPARATOR . 'database.sql.gz');
         $command = $this->getCommand('data:pushdb', 'db', $name, $args, $env, $log);
         $command->run(function ($type, $buffer) use($log) {
             $log->write($buffer);
         });
         if (!$command->isSuccessful()) {
             $cleanupFn();
             $log->write('Restore of database to "' . $name . '" failed: ' . $command->getErrorOutput());
             throw new RuntimeException($command->getErrorOutput());
         }
         $log->write('Restore of database to "' . $name . '" done');
     }
     // Restore assets
     if (in_array($dataTransfer->Mode, array('all', 'assets'))) {
         // Upload into target environment
         $log->write('Restore of assets to "' . $name . '" started');
         // Extract assets.tar.gz into assets/
         $extractCmd = sprintf('cd %s && tar xzf %s', escapeshellarg($tempPath), escapeshellarg($tempPath . DIRECTORY_SEPARATOR . 'assets.tar.gz'));
         $log->write($extractCmd);
         $process = new Process($extractCmd);
         $process->setTimeout(3600);
         $process->run();
         if (!$process->isSuccessful()) {
             $log->write('Could not extract the assets archive');
             $cleanupFn();
             throw new RuntimeException($process->getErrorOutput());
         }
         $args = array('data_path' => $tempPath . DIRECTORY_SEPARATOR . 'assets');
         $command = $this->getCommand('data:pushassets', 'web', $name, $args, $env, $log);
         $command->run(function ($type, $buffer) use($log) {
             $log->write($buffer);
         });
         if (!$command->isSuccessful()) {
             $cleanupFn();
             $log->write('Restore of assets to "' . $name . '" failed: ' . $command->getErrorOutput());
             throw new RuntimeException($command->getErrorOutput());
         }
         $log->write('Restore of assets to "' . $name . '" done');
     }
     $log->write('Rebuilding and cleaning up');
     $cleanupFn();
 }