Source of file LoadModulesTask.php
Size: 8,395 Bytes - Last Modified: 2021-12-23T10:25:21+00:00
/var/www/docs.ssmods.com/process/src/LoadModulesTask.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 | <?php include_once dirname(__FILE__) . '/SilverStripeBuildTask.php'; /** * A phing task to load modules from a specific URL via SVN or git checkouts * * Passes commands directly to the commandline to actually perform the * svn checkout/updates, so you must have these on your path when this * runs. * * @author Marcus Nyeholt <marcus@symbiote.com.au> * */ class LoadModulesTask extends SilverStripeBuildTask { /** * Character used to separate the module/revision name from the output path */ const MODULE_SEPARATOR = ':'; /** * The file that defines the dependency * * @var String */ private $file = ''; /** * Optionally specify a module name * * @var String */ private $name = ''; /** * And a module url * @var String */ private $url = ''; /** * Is this a non-interactive build session? * @var boolean */ private $nonInteractive = false; public function setNoninteractive($v) { if (!strpos($v, '${') && $v == 'true' || $v == 1) { $this->nonInteractive = true; } } public function setFile($v) { $this->file = $v; } public function setName($v) { $this->name = $v; } public function setUrl($v) { $this->url = $v; } public function main() { if ($this->name) { $this->loadModule($this->name, $this->url); } else { // load the items from the dependencies file if (!file_exists($this->file)) { throw new BuildException("Modules file " . $this->modulesFile . " cannot be read"); } $items = file($this->file); foreach ($items as $item) { $item = trim($item); if (strpos($item, '#') === 0) { continue; } $bits = preg_split('/\s+/', $item); // skip malformed lines if (count($bits) < 2) { continue; } $moduleName = trim($bits[0], '/'); $svnUrl = trim($bits[1], '/'); $storeLocally = false; if (isset($bits[2])) { $devBuild = $bits[2] == 'true'; $storeLocally = $bits[2] == 'local'; if (isset($bits[3])) { $storeLocally = $bits[3] == 'local'; } } $this->loadModule($moduleName, $svnUrl, $devBuild, $storeLocally); } } $this->devBuild(); } /** * Actually load the module! * * @param String $moduleName * @param String $svnUrl * @param boolean $devBuild * Do we run a dev/build? * @param boolean $storeLocally * Should we store the module locally, for it to be included in * the local project's repository? */ protected function loadModule($moduleName, $svnUrl, $devBuild = false, $storeLocally=false) { $git = strrpos($svnUrl, '.git') == (strlen($svnUrl) - 4); $branch = 'master'; $cmd = ''; $originalName = $moduleName; if (strpos($moduleName, self::MODULE_SEPARATOR) > 0) { $branch = substr($moduleName, strpos($moduleName, self::MODULE_SEPARATOR) + 1); $moduleName = substr($moduleName, 0, strpos($moduleName, self::MODULE_SEPARATOR)); } $md = $this->loadMetadata(); if (!isset($md['store'])) { // backwards compatibility $md['store'] = false; } // check the module out if it doesn't exist if (!file_exists($moduleName)) { echo "Check out $moduleName from $svnUrl\n"; // check whether it's git or svn if ($git) { if(strpos($branch, self::MODULE_SEPARATOR)) { $commit = substr($branch, strpos($branch, self::MODULE_SEPARATOR) + 1); } else { $commit = null; } $this->exec("git clone $svnUrl $moduleName"); $dir = getcwd(); chdir($moduleName); if($commit) { $this->exec("git checkout $commit"); } else { $currentBranch = $this->exec('git symbolic-ref HEAD', true); $currentBranch = substr(trim($currentBranch), strlen('refs/heads/')); if($currentBranch != $branch) { $this->exec("git checkout -t origin/$branch"); } } chdir($dir); if ($storeLocally) { rrmdir("$moduleName/.git"); } } else { $revision = ''; if ($branch != 'master') { $revision = " --revision $branch "; } $cmd = 'co'; if ($storeLocally) { $cmd = 'export'; } $this->exec("svn $cmd $revision $svnUrl $moduleName"); } // make sure to append it to the .gitignore file if (!$storeLocally && file_exists('.gitignore')) { $gitIgnore = file_get_contents('.gitignore'); if (strpos($gitIgnore, $moduleName) === false) { $this->exec("echo $moduleName >> .gitignore"); } } } else { echo "Updating $moduleName $branch from $svnUrl\n"; $overwrite = true; if (!$storeLocally) { $statCmd = $git ? "git diff --name-status" : "svn status"; $mods = trim($this->exec("cd $moduleName && $statCmd && cd \"$currentDir\"", true)); if (strlen($mods) && !$storeLocally) { $this->log("The following files are locally modified"); echo "\n $mods\n\n"; if (!$this->nonInteractive) { $overwrite = strtolower(trim($this->getInput("Overwrite local changes? [y/N]"))); $overwrite = $overwrite == 'y'; } } } $storedBranch = trim($md[$moduleName]['branch'], ':'); if (!$storedBranch) { $storedBranch = 'master'; // set the same default } // get the metadata and make sure it's not the same if ($md && isset($md[$moduleName]) && isset($md[$moduleName]['url'])) { if ($md[$moduleName]['url'] != $svnUrl || $md[$moduleName]['store'] != $storeLocally || $branch != $storedBranch) { if ($overwrite) { // delete the directory and reload the module echo "Deleting $moduleName on branch " . $md[$moduleName]['branch'] . " and reloading to branch $branch\n"; unset($md[$moduleName]); $this->writeMetadata($md); rrmdir($moduleName, true); $this->loadModule($originalName, $svnUrl, $devBuild, $storeLocally); return; } else { throw new Exception("You have chosen not to overwrite changes, but also want to change your " . "SCM settings. Please resolve changes and try again"); } } } if (!$storeLocally) { if ($git) { $commitId = null; if (strpos($branch, self::MODULE_SEPARATOR) > 0) { $commitId = substr($branch, strpos($branch, self::MODULE_SEPARATOR) + 1); $branch = substr($branch, 0, strpos($branch, self::MODULE_SEPARATOR)); } $currentDir = getcwd(); $currentBranch = trim($this->exec("cd $moduleName && git branch && cd \"$currentDir\"", true)); $overwriteOpt = $overwrite ? '-f' : ''; $this->exec("cd $moduleName && git checkout $overwriteOpt $branch && git pull origin $branch && cd \"$currentDir\""); if ($commitId) { $this->exec("cd $moduleName && git pull && git checkout $commitId && cd \"$currentDir\""); } } else { $revision = ''; if ($branch != 'master') { $revision = " --revision $branch "; } echo $this->exec("svn up $revision $moduleName"); } } } $metadata = array( 'url' => $svnUrl, 'store' => $storeLocally, 'branch' => str_replace($moduleName, '', $originalName), ); $md[$moduleName] = $metadata; $this->writeMetadata($md); // make sure to remove from the .gitignore file - don't need to do it EVERY // run, but it's better than munging code up above if ($storeLocally && file_exists('.gitignore')) { $gitIgnore = file('.gitignore'); $newIgnore = array(); foreach ($gitIgnore as $line) { $line = trim($line); if (!$line || $line == $moduleName || $line == "$moduleName/") { continue; } $newIgnore[] = $line; } file_put_contents('.gitignore', implode("\n", $newIgnore)); } if ($devBuild) { $this->devBuild(); } } protected function loadMetadata() { $metadataFile = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'phing-metadata'; $md = array(); if (file_exists($metadataFile)) { $md = unserialize(file_get_contents($metadataFile)); } return $md; } protected function writeMetadata($md) { $metadataFile = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'phing-metadata'; file_put_contents($metadataFile, serialize($md)); } } if (!function_exists('rrmdir')) { function rrmdir($dir) { if (is_dir($dir)) { $objects = scandir($dir); foreach ($objects as $object) { if ($object != "." && $object != "..") { if (filetype($dir . "/" . $object) == "dir") rrmdir($dir . "/" . $object); else unlink($dir . "/" . $object); } } reset($objects); rmdir($dir); } } } |