/** * Updates information in package.xml file used by packaged extensions */ static function run_update_package_xml($task = null, $args = array(), $cliopts = array()) { /// @todo replace hostname, build time $opts = self::getOpts(@$args[0], @$args[1], $cliopts); if (!SharedLock::acquire($opts['extension']['name'], LOCK_EX, $opts)) { throw new PakeException("Source code locked by another process"); } $destdir = $opts['build']['dir']; $files = pakeFinder::type('file')->name('package.xml')->maxdepth(0); if (count($files) == 1) { // original format pake_replace_regexp($files, $destdir, array('#^( *\\074name\\076)(.*)(\\074/name\\076\\r?\\n?)$#m' => '${1}' . $opts['extension']['name'] . '_extension' . '$3', '#^( *\\074version\\076)(.*)(\\074/version\\076\\r?\\n?)$#m' => '${1}' . $opts['ezp']['version']['major'] . '.' . $opts['ezp']['version']['minor'] . '.' . $opts['ezp']['version']['release'] . '$3', '#^( *\\074named-version\\076)(.*)(\\074/named-version\\076\\r?\\n?)$#m' => '${1}' . $opts['ezp']['version']['major'] . '.' . $opts['ezp']['version']['minor'] . '$3', '#^( *\\074number\\076)(.*)(\\074/number\\076\\r?\\n?)$#m' => '${1}' . $opts['version']['alias'] . '$3', '#^( *\\074release\\076)(.*)(\\074/release\\076\\r?\\n?)$#m' => '${1}' . $opts['version']['release'] . '$3', '#^( *\\074timestamp\\076)(.*)(\\074/timestamp\\076\\r?\\n?)$#m' => '${1}' . time() . '$3', '#^( *\\074host\\076)(.*)(\\074/host\\076\\r?\\n?)$#m' => '${1}' . gethostname() . '$3', '#^( *\\074licence\\076)(.*)(\\074/licence\\076\\r?\\n?)$#m' => '${1}' . $opts['version']['license'] . '$3')); // replacing a token based on its value instead of its location (text immediately before and after, // as done above) has a disadvantage: we cannot execute the substitution many // times on the same text, as the 1st substitution will remove the token's // value. This means we have to reinit the build to get a 100% updated // package file. Unfortunately hunting for xml attributes not based on // token values needs a real xml parser, simplistic regexps are not enough... pake_replace_tokens($files, $destdir, '{', '}', array('$name' => $opts['extension']['name'], '$version' => $opts['version']['alias'], '$ezp_version' => $opts['ezp']['version']['major'] . '.' . $opts['ezp']['version']['minor'] . '.' . $opts['ezp']['version']['release'])); } SharedLock::release($opts['extension']['name'], LOCK_EX, $opts); }
/** * Commits changelog to the "ci" git repo and updates in there other files holding version-related infos; options: skip-update-ci-repo-source * As part of this task, the local copy of the "ci" git repo is updated from upstream. * * The "ci" repo is used by the standard eZ Publish build process, driven by Jenkins. * It holds, amongs other things, patch files that are applied in order to build the * CP version instead of the Enterprise one */ public static function run_update_ci_repo($task = null, $args = array(), $cliopts = array()) { $opts = self::getOpts($args, $cliopts); $rootpath = self::getSourceDir($opts, 'legacy'); // start work on the ci repo: $cipath = self::getSourceDir($opts, 'ci-repo'); $git = self::getTool('git', $opts); // 1. update ci repo - moved to a separate task // dirty, dirty hack $originp = @$GLOBALS['originp']; $repo = new pakeGit($cipath); if ($opts['git']['ci-repo']['path'] != '') { $cipath .= '/' . $opts['git']['ci-repo']['path']; $localcipath = $opts['git']['ci-repo']['path'] . '/'; } else { $localcipath = ''; } // 1b. check that there is no spurious stuff in changelog dir, or step 3 later will create bad patch files. // we do this here to avoid adding ANY file to local copy of CI git repo and abort asap $changelogdir = 'doc/changelogs/Community_Project-' . $opts['version']['major']; $files = pakeFinder::type('file')->maxdepth(0)->relative()->in(self::getSourceDir($opts, 'legacy') . '/' . $changelogdir); if (count($files) != 1) { throw new pakeException("More than one changelog file (or none) found in directory {$changelogdir}, can not generate patch file for CI repo"); } // 2. update 0002_2011_11_patch_fix_version.diff file $files1 = pakeFinder::type('file')->name('0002_2011_11_patch_fix_version.diff')->maxdepth(0)->relative()->in($cipath . '/patches'); $files2 = pakeFinder::type('file')->name('0003_2011_11_patch_fix_package_repository.diff')->maxdepth(0)->relative()->in($cipath . '/patches'); /// @todo what if those files are gone? $patchfile1 = $cipath . '/patches/' . $files1[0]; $patchfile2 = $cipath . '/patches/' . $files2[0]; // if a new major version has been released, the '0002_2011_11_patch_fix_version.diff' patch will not apply, // and the '0003_2011_11_patch_fix_package_repository.diff' file will have to be altered as well // we need thus to regenerate them (more details: https://docs.google.com/a/ez.no/document/d/1h5n3aZdXbyo9_iJoDjoDs9a6GdFZ2G-db9ToK7J1Gck/edit?hl=en_GB) // 1st, we test that the current patch file will apply cleanly (if it does, we assume no new EE release) $patch = self::getTool('patch', $opts); $patcherror = false; try { $patchResult = pake_sh(self::getCdCmd($rootpath) . " && {$patch} --dry-run -p0 < " . $patchfile1); } catch (Exception $e) { $patcherror = $e->getMessage(); } // then, we (try to) recover version info from existing patch files $patch1 = file_get_contents($patchfile1); $patch2 = file_get_contents($patchfile2); if (preg_match('/^\\- +const +VERSION_MAJOR += +(\\d+);/m', $patch1, $m1) && preg_match('/^\\- +const +VERSION_MINOR += +(\\d+);/m', $patch1, $m2) && preg_match('/^\\+RemotePackagesIndexURL=http:\\/\\/packages.ez.no\\/ezpublish\\/[^\\/]+\\/(.+)$/m', $patch2, $m3)) { $oldNextVersionMajor = $m1[1]; $oldNextVersionMinor = $m2[1]; $currentVersion = $m3[1]; // give some information to user pake_echo("\nPackages available during setup wizard execution for this CP build will be the ones from eZP {$currentVersion}"); pake_echo("The next build of eZ Publish EE is expected to be {$oldNextVersionMajor}.{$oldNextVersionMinor}\n"); // last, we try automated fixing or abort if ($patcherror) { // try to gather enough information to fix automatically the patch files $currfile = file_get_contents($rootpath . '/lib/version.php'); if (preg_match('/^\\ +const +VERSION_MAJOR += +(\\d+);/m', $currfile, $m1) && preg_match('/^\\ +const +VERSION_MINOR += +(\\d+);/m', $currfile, $m2)) { $newNextVersionMajor = $m1[1]; $newNextVersionMinor = $m2[1]; if ($newNextVersionMajor == $oldNextVersionMajor && $newNextVersionMinor == $oldNextVersionMinor) { // patch does not apply but version number was not changed. Abort throw new pakeException("The diff file {$patchfile1} does not apply correctly, build will fail. Please fix it, commit and push.\n Also check to fix if needed the url to packages repo in 0003_2011_11_patch_fix_package_repository.diff.\nError details:\n" . $patcherror); } pake_echo("It seems that EE version {$oldNextVersionMajor}.{$oldNextVersionMinor} was released, next expected EE version is currently {$newNextVersionMajor}.{$newNextVersionMinor}"); pake_echo("This means that the diff file {$patchfile1} does not apply correctly, the build will fail."); pake_echo("The script can fix this automatically, or you will have to fix patch files by hand (at least 2 of them)"); pake_echo("Proposed changes:"); pake_echo("Packages available during setup wizard execution for this CP build will be the ones from eZP {$oldNextVersionMajor}.{$oldNextVersionMinor}.0"); $ok = pake_input("Do you want to continue with automatic fixing? [y/n]", 'n'); if ($ok != 'y') { throw new pakeException("Please fix patch file by hand, commit and push.\nAlso remember to fix the url to packages repo in 0003_2011_11_patch_fix_package_repository.diff"); } else { pake_replace_regexp($files1, $cipath . '/patches', array('/^- +const +VERSION_MAJOR += +\\d+;/m' => "+ const VERSION_MAJOR = {$newNextVersionMajor};", '/^- +const +VERSION_MINOR += +\\d+;/m' => "+ const VERSION_MINOR = {$newNextVersionMinor};")); pake_replace_regexp($files2, $cipath . '/patches', array('/^\\+RemotePackagesIndexURL=http:\\/\\/packages.ez.no\\/ezpublish\\/([^\\/]+)\\/.*$/m' => "+RemotePackagesIndexURL=http://packages.ez.no/ezpublish/{$oldNextVersionMajor}.{$oldNextVersionMinor}/{$oldNextVersionMajor}.{$oldNextVersionMinor}.0")); } } else { throw new pakeException("The diff file {$patchfile1} does not apply correctly, build will fail. Please fix it, commit and push.\n Also remember to fix the url to packages repo in 0003_2011_11_patch_fix_package_repository.diff.\nError details:\n" . $patcherror); } } } else { if ($patcherror) { throw new pakeException("The diff file {$patchfile1} does not apply correctly, build will fail. Please fix it, commit and push.\n Also remember to fix the url to packages repo in 0003_2011_11_patch_fix_package_repository.diff.\nError details:\n" . $patcherror); } else { /// @todo waht to do here? warn user and give him a chance to abort... } } // finally, the changes which apply every time pake_replace_regexp($files1, $cipath . '/patches', array('/^\\+ +const +VERSION_MAJOR += +\\d+;/m' => "+ const VERSION_MAJOR = {$opts['version']['major']};", '/^\\+ +const +VERSION_MINOR += +\\d+;/m' => "+ const VERSION_MINOR = {$opts['version']['minor']};")); $repo->add(array($localcipath . 'patches/0002_2011_11_patch_fix_version.diff')); // 3. generate changelog diff // get absolute path to build dir $absrootpath = pakeFinder::type('directory')->name(self::getProjName())->in($opts['build']['dir'] . '/source'); $absrootpath = dirname($absrootpath[0]); $difffile = $absrootpath . '/' . $opts['version']['alias'] . '_patch_fix_changelog.diff'; pake_sh(self::getCdCmd($rootpath) . " && {$git} add " . escapeshellarg($changelogdir)); pake_sh(self::getCdCmd($rootpath) . " && {$git} diff --no-prefix --staged -- " . escapeshellarg($changelogdir) . " > " . escapeshellarg($difffile)); /// unstage the file pake_sh(self::getCdCmd($rootpath) . " && {$git} reset HEAD --"); // 4. add new changelog file /// calculate sequence nr. $max = 0; $files = pakeFinder::type('file')->maxdepth(0)->in($cipath . '/patches'); foreach ($files as $file) { $nr = (int) substr(basename($file), 0, 4); if ($nr > $max) { $max = $nr; } } $seqnr = str_pad($max + 1, 4, '0', STR_PAD_LEFT); $newdifffile = $seqnr . '_' . str_replace('.', '_', $opts['version']['alias']) . '_patch_fix_changelog.diff'; // what if there is already a patch file in the ci repo which creates the changelog we are adding a patch file for? if (preg_match_all('/^\\+\\+\\+ (.*)$/m', file_get_contents($difffile), $matches)) { $added = $matches[1]; //echo "adding: "; var_dump( $added ); $patchfiles = pakeFinder::type('file')->name('*.diff')->maxdepth(0)->in($cipath . '/patches'); foreach ($patchfiles as $patchfile) { if (preg_match_all('/^\\+\\+\\+ (.*)$/m', file_get_contents($patchfile), $matches)) { //echo "already added: "; var_dump( $matches[1] ); if (array_intersect($added, $matches[1])) { $cont = pake_select_input("The patch file\n {$patchfile}\nseems to already create the same files wew want to create using a new patch file:\n {$newdifffile}\n" . "This is a sign of a probable error somewhere. Press '1' to continue the build task anyway. Otherwise press '2' to exit.", array('Continue', 'Stop'), 1); if ($cont != 'Y') { exit; } } } } } pake_copy($difffile, $cipath . '/patches/' . $newdifffile, array('override' => true)); $repo->add(array($localcipath . 'patches/' . $newdifffile)); // 5. update ezpublish-gpl.properties $files = pakeFinder::type('file')->name('ezpublish-gpl.properties')->maxdepth(0)->relative()->in($cipath . '/properties'); pake_replace_regexp($files, $cipath . '/properties', array('/^ezp\\.cp\\.version\\.major += +.+$/m' => "ezp.cp.version.major = {$opts['version']['major']}", '/^ezp\\.cp\\.version\\.minor += +.+$/m' => "ezp.cp.version.minor = {$opts['version']['minor']}")); $repo->add(array($localcipath . 'properties/ezpublish-gpl.properties')); // 5. commit changes and push to upstream $repo->commit('Prepare files for build of CP ' . $opts['version']['alias']); /// @todo allow the user to specify this on the command line if ($originp == '') { pake_echo("WARNING: Using \"origin\" as name of upstream repo as actual name not found"); $originp = "origin"; } pake_sh(self::getCdCmd($cipath) . " && {$git} push {$originp} {$opts['git']['ci-repo']['branch']}:{$opts['git']['ci-repo']['branch']}"); }