/** * {@inheritdoc} */ public function run(JobInterface $job, $data) { // Data format: // i) array('patch_file' => '...', 'patch_dir' => '...') // or // iii) array(array(...), array(...)) // Normalize data to the third format, if necessary $data = count($data) == count($data, COUNT_RECURSIVE) ? [$data] : $data; $job->getOutput()->writeln("<info>Entering setup_patch().</info>"); foreach ($data as $key => $details) { if (empty($details['patch_file'])) { $job->errorOutput("Error", "No valid patch file provided for the patch command."); return; } $workingdir = realpath($job->getWorkingDir()); $patchfile = $details['patch_file']; $patchdir = !empty($details['patch_dir']) ? $details['patch_dir'] : $workingdir; // Validate target directory. if (!($directory = $this->validate_directory($job, $patchdir))) { // Invalid checkout directory $job->errorOutput("Error", "The patch directory <info>{$directory}</info> is invalid."); return; } $cmd = "patch -p1 -i {$patchfile} -d {$directory}"; exec($cmd, $cmdoutput, $result); if ($result !== 0) { // The command threw an error. $job->errorOutput("Patch failed", "The patch attempt returned an error."); $job->getOutput()->writeln($cmdoutput); // TODO: Pass on the actual return value for the patch attempt return; } $job->getOutput()->writeln("<comment>Patch <options=bold>{$patchfile}</options=bold> applied to directory <options=bold>{$directory}</options=bold></comment>"); } }
protected function setupCheckoutGit(JobInterface $job, $details) { $job->getOutput()->writeln("<info>Entering setup_checkout_git().</info>"); $repo = isset($details['repo']) ? $details['repo'] : 'git://drupalcode.org/project/drupal.git'; $gitbranch = isset($details['branch']) ? $details['branch'] : 'master'; $gitdepth = isset($details['depth']) ? $details['depth'] : NULL; $workingdir = $job->getWorkingDir(); $checkoutdir = isset($details['checkout_dir']) ? $details['checkout_dir'] : $workingdir; // TODO: Ensure we don't end up with double slashes // Validate target directory. Must be within workingdir. if (!($directory = $this->validate_directory($job, $checkoutdir))) { // Invalid checkout directory $job->errorOutput("Error", "The checkout directory <info>{$directory}</info> is invalid."); return; } $job->getOutput()->writeln("<comment>Performing git checkout of {$repo} {$gitbranch} branch to {$directory}.</comment>"); $cmd = "git clone -b {$gitbranch} {$repo} {$directory}"; if (!is_null($gitdepth)) { $cmd .= " --depth={$gitdepth}"; } exec($cmd, $cmdoutput, $result); if ($result !== 0) { // Git threw an error. $job->errorOutput("Checkout failed", "The git checkout returned an error."); // TODO: Pass on the actual return value for the git checkout return; } $job->getOutput()->writeln("<comment>Checkout complete.</comment>"); }
protected function validate_directory(JobInterface $job, $dir) { // Validate target directory. Must be within workingdir. $working_dir = $job->getWorkingDir(); $true_dir = realpath($dir); if (!empty($true_dir)) { if ($true_dir == realpath($working_dir)) { // Passed directory is the root working directory. return $true_dir; } elseif (strpos($true_dir, realpath($working_dir)) === 0) { // Passed directory is an existing subdirectory within the working path. return $true_dir; } } // Assume the Passed directory is a subdirectory of the working, without the working prefix. Construct the full path. if (!(strpos($dir, realpath($working_dir)) === 0)) { $dir = $working_dir . "/" . $dir; } $directory = realpath($dir); // TODO: Ensure we don't have double slashes // Check whether this is a pre-existing directory if ($directory === FALSE) { // Directory doesn't exist. Create and then validate. mkdir($dir, 0777, TRUE); $directory = realpath($dir); } // Validate that resulting directory is still within the working directory path. if (!strpos(realpath($directory), realpath($working_dir)) === 0) { // Invalid checkout directory $job->errorOutput("Error", "The checkout directory <info>{$directory}</info> is invalid."); return FALSE; } // Return the updated directory value. return $directory; }
/** * {@inheritdoc} */ public function run(JobInterface $job, $data) { // Data format: // i) array('url' => '...', 'fetch_dir' => '...') // or // iii) array(array(...), array(...)) // Normalize data to the third format, if necessary $data = count($data) == count($data, COUNT_RECURSIVE) ? [$data] : $data; $job->getOutput()->writeln("<info>Entering setup_fetch().</info>"); foreach ($data as $key => $details) { // URL and target directory // TODO: Ensure $details contains all required parameters if (empty($details['url'])) { $job->errorOutput("Error", "No valid target file provided for fetch command."); return; } $url = $details['url']; $workingdir = realpath($job->getWorkingDir()); $fetchdir = !empty($details['fetch_dir']) ? $details['fetch_dir'] : $workingdir; if (!($directory = $this->validate_directory($job, $fetchdir))) { // Invalid checkout directory $job->errorOutput("Error", "The fetch directory <info>{$directory}</info> is invalid."); return; } $info = pathinfo($url); $destfile = $directory . "/" . $info['basename']; $contents = file_get_contents($url); if ($contents === FALSE) { $job->errorOutput("Error", "An error was encountered while attempting to fetch <info>{$url}</info>."); return; } if (file_put_contents($destfile, $contents) === FALSE) { $job->errorOutput("Error", "An error was encountered while attempting to write <info>{$url}</info> to <info>{$directory}</info>"); return; } $job->getOutput()->writeln("<comment>Fetch of <options=bold>{$url}</options=bold> to <options=bold>{$destfile}</options=bold> complete.</comment>"); } }