/** * Copies a file into a special test results directory for the build and * parse the xml file to generate statistics * * @param Xinc_Build_Interface $build The actuall build. * @param string $sourceFile The xml file to read out. * * @return boolean True if registering was ok, false if it failed. */ public function registerResults(Xinc_Build_Interface $build, $sourceFile) { $statusDir = Xinc::getInstance()->getStatusDir(); $projectDir = Xinc::getInstance()->getProjectDir(); $subDir = $build->getStatusSubDir(); $fullDir = $statusDir . DIRECTORY_SEPARATOR . $subDir . DIRECTORY_SEPARATOR . self::TESTRESULTS_DIR; $targetFile = $fullDir . DIRECTORY_SEPARATOR . basename($sourceFile); /** * Verify that the source is in the projectdir */ $relativePath = str_replace($projectDir, '', $sourceFile); if ($relativePath == $sourceFile) { /** * the filename was not within the project path, * we need to prevent this file from being copied. * * Future: run Xinc in a chroot environment per project */ $build->error('Registering test results: ' . $sourceFile . '->' . $targetFile . ' failed.'); $build->error('-- ' . $sourceFile . ' is not within project dir. Security Problem.'); return false; } if (!file_exists($fullDir)) { mkdir($fullDir, 0755, true); } if (is_dir($sourceFile)) { if (DIRECTORY_SEPARATOR == '\\') { exec('xcopy /E /Y /I ' . $sourceFile . ' ' . $targetFile, $out, $res); //chmod($targetFile, 0755); } else { exec('cp -Rf ' . $sourceFile . ' ' . $targetFile, $out, $res); } if ($res == 0) { $status = 'OK'; } else { $status = 'FAILURE'; } } elseif (is_file($sourceFile)) { $res = copy($sourceFile, $targetFile); if ($res) { chmod($targetFile, 0755); $status = 'OK'; /** * register statistics */ $build->getInternalProperties()->set('phpunit.file', $targetFile); $this->generateStats($build, $targetFile); } else { $status = 'FAILURE'; } } else { $build->error('The phpunit file ' . $sourceFile . ' couldn\'t be read.'); return false; } $build->info('Registering test results: ' . $sourceFile . '->' . $targetFile . ', result: ' . $status); return $res; }
/** * Checks whether the Subversion project has been modified. * * @param Xinc_Build_Interface $build The running build. * @param Xinc_Plugin_Repos_ModificationSet_Svn_Task $task The configured task * * @return Xinc_Plugin_Repos_ModificationSet_Result The result of the check. */ public function checkModified(Xinc_Build_Interface $build, Xinc_Plugin_Repos_ModificationSet_Svn_Task $task) { $result = new Xinc_Plugin_Repos_ModificationSet_Result(); try { $this->task = $task; $this->svn = VersionControl_SVN::factory(array('info', 'log', 'status', 'update'), array('fetchmode' => VERSIONCONTROL_SVN_FETCHMODE_ASSOC, 'username' => $task->getUsername(), 'password' => $task->getPassword(), 'trustServerCert' => $task->trustServerCert())); $strRemoteVersion = $this->getRemoteVersion(); $strLocalVersion = $this->getLocalVersion(); } catch (VersionControl_SVN_Exception $e) { $build->error('Test of Subversion failed: ' . $e->getMessage()); $build->setStatus(Xinc_Build_Interface::FAILED); $result->setStatus(Xinc_Plugin_Repos_ModificationSet_AbstractTask::ERROR); return $result; } $result->setRemoteRevision($strRemoteVersion); $result->setLocalRevision($strLocalVersion); if ($strRemoteVersion !== $strLocalVersion) { try { $this->getModifiedFiles($result); $this->getChangeLog($result); if ($this->task->doUpdate()) { $this->update($result); } $result->setStatus(Xinc_Plugin_Repos_ModificationSet_AbstractTask::CHANGED); } catch (Exception $e) { var_dump($e->getMessage()); $build->error('Processing SVN failed: ' . $e->getMessage()); $result->setStatus(Xinc_Plugin_Repos_ModificationSet_AbstractTask::FAILED); } } return $result; }
/** * Check if this modification set has been modified * * @param Xinc_Build_Interface $build The running build. * @param Xinc_Plugin_Repos_ModificationSet_Git_Task $task The configured task * * @return Xinc_Plugin_Repos_ModificationSet_Result The result of the check. */ public function checkModified(Xinc_Build_Interface $build, Xinc_Plugin_Repos_ModificationSet_Git_Task $task) { $result = new Xinc_Plugin_Repos_ModificationSet_Result(); try { $this->git = new VersionControl_Git($task->getDirectory()); $strBranch = $this->git->getCurrentBranch(); $strRemoteHash = $this->getRemoteHash($strBranch); $strLocalHash = $this->getLocalHash($strBranch); } catch (Exception $e) { $build->error('Test of GIT Repos failed: ' . $e->getMessage()); $build->setStatus(Xinc_Build_Interface::FAILED); $result->setStatus(Xinc_Plugin_Repos_ModificationSet_AbstractTask::FAILED); return $result; } $result->setRemoteRevision($strRemoteHash); $result->setLocalRevision($strLocalHash); if ($strRemoteHash !== $strLocalHash) { $this->fetch(); $this->getModifiedFiles($result); $this->getChangeLog($result); if ($task->getUpdate()) { try { $this->update(); } catch (Exception $e) { $build->error('Update of GIT local failed: ' . $e->getMessage()); $result > setStatus(Xinc_Plugin_Repos_ModificationSet_AbstractTask::FAILED); return $result; } } $result->setStatus(Xinc_Plugin_Repos_ModificationSet_AbstractTask::CHANGED); } return $result; }
public function checkModified(Xinc_Build_Interface $build, $dir, $prefix, $switch = false, $svnFolderProperty = null) { $modResult = new Xinc_Plugin_Repos_ModificationSet_Result(); if (!file_exists($dir)) { $build->error('Subversion checkout directory not present'); $modResult->setStatus(Xinc_Plugin_Repos_ModificationSet_AbstractTask::ERROR); return $modResult; } $cwd = getcwd(); chdir($dir); $output = ''; $result = 9; exec($this->_svnPath . ' info', $output, $result); $found = false; if ($result == 0) { $localSet = implode("\n", $output); $localRev = $this->getRevision($localSet); $remoteRev = 0; $url = $this->getRootURL(); $output = ''; $result = 9; exec($this->_svnPath . ' ls --xml ' . $url . '/' . $this->_getSvnSubDir(), $output, $result); $remoteSet = implode("\n", $output); if ($result != 0) { $build->setStatus(Xinc_Build_Interface::FAILED); $build->error('Problem with remote Subversion repository'); $modResult->setStatus(Xinc_Plugin_Repos_ModificationSet_AbstractTask::ERROR); return $modResult; } $xml = new SimplexmlElement($remoteSet); foreach ($xml->list as $i => $list) { foreach ($list->entry as $entry) { if (substr($entry->name, 0, strlen($prefix)) != $prefix && !preg_match('/' . $prefix . '/', $entry->name)) { continue; } $attributes = $entry->attributes(); if (strtolower((string) $attributes['kind']) != 'dir') { continue; } $attributes = $entry->commit->attributes(); $rev = (int) $attributes->revision; if ($rev > $localRev) { $tagName = (string) $entry->name; if ($svnFolderProperty != null) { $build->getProperties()->set($svnFolderProperty, $tagName); } // switch to the latest release if ($switch) { exec($this->_svnPath . ' switch ' . $url . '/' . $this->_getSvnSubDir() . '/' . $tagName, $switchOut, $switchRes); if ($switchRes != 0) { $build->error('Could not switch to tag :' . $tagName . ', result:' . implode("\n", $switchOut)); $build->setStatus(Xinc_Build_Interface::FAILED); $modResult->setStatus(Xinc_Plugin_Repos_ModificationSet_AbstractTask::FAILED); return $modResult; } } $remoteRev = $rev; $found = true; } } } if ($remoteRev <= 0) { $build->info('Subversion checkout dir is ' . $dir . ' ' . 'local revision @ ' . $localRev . ' ' . 'No remote revision with matching tag prefix (' . $prefix . ')'); } else { $build->info('Subversion checkout dir is ' . $dir . ' ' . 'local revision @ ' . $localRev . ' ' . 'Last remote revision with matching tag prefix @ ' . $remoteRev . ' (' . $prefix . ')'); } chdir($cwd); $modResult->setLocalRevision($localRev); $modResult->setRemoteRevision($remoteRev); if ($modResult->isChanged()) { $modResult->setStatus(Xinc_Plugin_Repos_ModificationSet_AbstractTask::CHANGED); } return $modResult; } else { chdir($cwd); throw new Xinc_Exception_ModificationSet('Subversion checkout directory ' . 'is not a working copy.'); } }
/** * loads properties from a property file * * @param Xinc_Build_Interface $build * @param string $fileName */ public function parsePropertyFile(Xinc_Build_Interface $build, $fileName) { $activeProperty = false; $trimNextLine = false; $arr = array(); $fh = fopen($fileName, 'r'); if (is_resource($fh)) { while ($line = fgets($fh)) { if (preg_match('/^[!#].*/', $line)) { // comment } else { if (preg_match("/^.*?([\\._-\\w]+?)\\s*[=:]+\\s*(.*)\$/", $line, $matches)) { // we have a key definition $activeProperty = true; $key = $matches[1]; $valuePart = $matches[2]; $arr[$key] = trim($valuePart); if ($arr[$key][strlen($arr[$key]) - 1] == '\\') { $arr[$key] = substr($arr[$key], 0, -1); $trimNextLine = true; } else { $trimNextLine = false; } } else { if ($activeProperty) { $trimmed = trim($line); if (empty($trimmed)) { $activeProperty = false; continue; } else { if ($trimNextLine) { $line = $trimmed; } else { $line = rtrim($line); } } $arr[$key] .= "\n" . $line; if ($arr[$key][strlen($arr[$key]) - 1] == '\\') { $arr[$key] = substr($arr[$key], 0, -1); $trimNextLine = true; } else { $trimNextLine = false; } } } } } foreach ($arr as $key => $value) { $build->debug('Setting property "${' . $key . '}" to "' . $value . '"'); $build->getProperties()->set($key, stripcslashes($value)); } } else { $build->error('Cannot read from property file: ' . $fileName); } }
/** * Serializes a build an catches the exceptions * * @param Xinc_Build_Interface $build * * @return void */ protected function serializeBuild(Xinc_Build_Interface $build) { try { $build->serialize(); } catch (Xinc_Build_Exception_NotRun $e1) { $build->error('Build cannot be serialized, it did not run.'); } catch (Xinc_Build_Exception_Serialization $e2) { $build->error('Build could not be serialized properly.'); } catch (Xinc_Build_History_Exception_Storage $e3) { $build->error('Build history could not be stored.'); } catch (Exception $e4) { $build->error('Unknown error occured while serializing the build.'); } }
/** * calling phing * * @param Xinc_Build_Interface $build * @param string $buildfile * @param string $target * @param string $extraParams * @param string $workingDir * * @return boolean */ public function build(Xinc_Build_Interface $build, $buildfile, $target, $extraParams = null, $workingDir = null) { //$phing = new Phing(); $logLevel = Xinc_Logger::getInstance()->getLogLevel(); $arguments = array(); switch ($logLevel) { case Xinc_Logger::LOG_LEVEL_VERBOSE: $arguments[] = '-verbose'; break; } $oldPwd = getcwd(); /** * set workingdir if not set from task, * use project dir */ if ($workingDir == null) { $workingDir = Xinc::getInstance()->getProjectDir() . DIRECTORY_SEPARATOR . $build->getProject()->getName(); } if (is_dir($workingDir)) { Xinc_Logger::getInstance()->debug('Switching to directory: ' . $workingDir); chdir($workingDir); } $logFile = getcwd() . DIRECTORY_SEPARATOR . md5($build->getProject()->getName() . time()) . '.log'; if (file_exists($logFile)) { unlink($logFile); } $arguments[] = '-logger'; //$arguments[] = 'phing.listener.DefaultLogger'; $arguments[] = 'phing.listener.NoBannerLogger'; $arguments[] = '-logfile'; $arguments[] = $logFile; $arguments[] = '-buildfile'; $arguments[] = $buildfile; if ($target != null) { $arguments[] = $target; } $arguments[] = '-Dxinc.buildlabel=' . $this->_encodeParam($build->getLabel()); $arguments[] = '-Dprojectname=' . $this->_encodeParam($build->getProject()->getName()); $arguments[] = '-Dcctimestamp=' . $this->_encodeParam($build->getBuildTime()); foreach ($build->getProperties()->getAllProperties() as $name => $value) { $arguments[] = '-Dxinc.' . $this->_encodeParam($name) . '=' . $this->_encodeParam($value); } try { $phingPath = Xinc_Ini::getInstance()->get('path', 'phing'); } catch (Exception $e) { $phingPath = null; } if (empty($phingPath)) { if (DIRECTORY_SEPARATOR != '/') { /** * windows has the phing command inside the bin_dir directory */ $phingPath = PEAR_Config::singleton()->get('bin_dir') . DIRECTORY_SEPARATOR . 'phing'; } else { $phingPath = 'phing'; } } if (DIRECTORY_SEPARATOR == '/') { $redirect = "2>&1"; } else { $redirect = ""; } $command = $phingPath . ' ' . implode(' ', $arguments) . ' ' . $extraParams . ' ' . $redirect; exec($command, $output, $returnValue); chdir($oldPwd); $buildSuccess = false; if (file_exists($logFile)) { $fh = fopen($logFile, 'r'); if (is_resource($fh)) { while ($line = fgets($fh)) { Xinc_Logger::getInstance()->info($line); if (strstr($line, "BUILD FINISHED")) { $buildSuccess = true; } } fclose($fh); } unlink($logFile); } if (count($output) > 0) { Xinc_Logger::getInstance()->error('Errors on command line:'); foreach ($output as $line) { Xinc_Logger::getInstance()->error($line); } } switch ($returnValue) { case 0: case 1: if ($buildSuccess) { return true; } else { $build->error('Phing command ' . $command . ' exited with status: ' . $returnValue); $build->setStatus(Xinc_Build_Interface::FAILED); return false; } break; case -1: case -2: $build->error('Phing build script: ' . $command . ' exited with status: ' . $returnValue); $build->setStatus(Xinc_Build_Interface::FAILED); return false; break; } return false; }