From: Michael M Slusarz Date: Wed, 23 Dec 2009 01:20:45 +0000 (-0700) Subject: Import admintools and devtools from CVS HEAD X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=43d7cc98330fca9a9d8b14564cb6d430c9b5083b;p=horde.git Import admintools and devtools from CVS HEAD --- diff --git a/framework/admintools/README b/framework/admintools/README new file mode 100644 index 000000000..eca9724d1 --- /dev/null +++ b/framework/admintools/README @@ -0,0 +1,20 @@ +========================= +Horde Administrator Tools +========================= + +Introduction +------------ + +This directory contains various utility scripts for Horde administrators. + + +Script Index +------------ + +horde-remove-prefs.php + Remove all entries of a preference name/scope combination from an + SQL prefs backend. + +horde-update.sh + Facilitates the updating and/or installation of horde and its + applications. diff --git a/framework/admintools/horde-base.php b/framework/admintools/horde-base.php new file mode 100644 index 000000000..67a5e8bca --- /dev/null +++ b/framework/admintools/horde-base.php @@ -0,0 +1,11 @@ + + */ + +// Do CLI checks and environment setup first. +require_once dirname(__FILE__) . '/horde-base.php'; +require_once $horde_base . '/lib/core.php'; + +// Make sure no one runs this from the web. +if (!Horde_Cli::runningFromCLI()) { + exit("Must be run from the command line\n"); +} + +// Load the CLI environment - make sure there's no time limit, init +// some variables, etc. +$cli = Horde_Cli::singleton(); +$cli->init(); + +// Include needed libraries. +$horde_authentication = 'none'; +require_once HORDE_BASE . '/lib/base.php'; + +$db_lib = 'DB'; +$sequence = null; +if (isset($_SERVER['argv']) && count($_SERVER['argv']) >= 2) { + array_shift($_SERVER['argv']); + while ($arg = array_shift($_SERVER['argv'])) { + if ($arg == '--mdb2') { + $db_lib = 'MDB2'; + } else { + $sequence = $arg; + } + } +} +if (is_null($sequence)) { + $sequence = $cli->prompt(_("What sequence do you want to create (_seq will be added automatically)?")); +} + +switch ($db_lib) { +case 'DB': + require_once 'DB.php'; + $dbh = DB::connect($conf['sql']); + break; + +case 'MDB2': + require_once 'MDB2.php'; + $params = $conf['sql']; + unset($params['charset']); + $dbh = MDB2::factory($params); + break; + +default: + throw new Horde_Exception('Unknown database abstraction library'); +} +if (is_a($dbh, 'PEAR_Error')) { + throw new Horde_Exception($dbh); +} + +if (!preg_match('/^\w+$/', $sequence)) { + $cli->fatal('Invalid sequence name'); +} + +switch ($db_lib) { +case 'DB': + $result = $dbh->createSequence($sequence); + break; + +case 'MDB2': + $dbh->loadModule('Manager', null, true); + $result = $dbh->manager->createSequence($sequence); + break; +} +if (is_a($result, 'PEAR_Error')) { + $cli->fatal($result->getMessage()); +} + +$cli->green('Sequence created.'); +exit(0); diff --git a/framework/admintools/horde-db-dumpdata.php b/framework/admintools/horde-db-dumpdata.php new file mode 100755 index 000000000..7b69846a8 --- /dev/null +++ b/framework/admintools/horde-db-dumpdata.php @@ -0,0 +1,46 @@ +#!@php_bin@ + + * @category Horde + * @package admintools + */ + +// Do CLI checks and environment setup first. +require_once dirname(__FILE__) . '/horde-base.php'; +require_once $horde_base . '/lib/core.php'; + +// Make sure no one runs this from the web. +if (!Horde_Cli::runningFromCLI()) { + exit("Must be run from the command line\n"); +} + +// Load the CLI environment - make sure there's no time limit, init +// some variables, etc. +$cli = Horde_Cli::singleton(); +$cli->init(); + +// Include needed libraries. +$horde_authentication = 'none'; +require_once HORDE_BASE . '/lib/base.php'; + +$manager = Horde_SQL_Manager::getInstance(); +if (is_a($manager, 'PEAR_Error')) { + $cli->fatal($manager->toString()); +} + +// Get rid of the script name +array_shift($_SERVER['argv']); +$tables = array_values($_SERVER['argv']); + +$result = $manager->dumpData('php://stdout', $tables); +if (is_a($result, 'PEAR_Error')) { + $cli->fatal($result->toString()); +} + +exit(0); diff --git a/framework/admintools/horde-db-dumpschema.php b/framework/admintools/horde-db-dumpschema.php new file mode 100755 index 000000000..4f31867cb --- /dev/null +++ b/framework/admintools/horde-db-dumpschema.php @@ -0,0 +1,47 @@ +#!@php_bin@ + + * @category Horde + * @package admintools + */ + +// Do CLI checks and environment setup first. +require_once dirname(__FILE__) . '/horde-base.php'; +require_once $horde_base . '/lib/core.php'; + +// Make sure no one runs this from the web. +if (!Horde_Cli::runningFromCLI()) { + exit("Must be run from the command line\n"); +} + +// Load the CLI environment - make sure there's no time limit, init +// some variables, etc. +$cli = Horde_Cli::singleton(); +$cli->init(); + +// Include needed libraries. +$horde_authentication = 'none'; +require_once HORDE_BASE . '/lib/base.php'; + +$manager = Horde_SQL_Manager::getInstance(); +if (is_a($manager, 'PEAR_Error')) { + $cli->fatal($manager->toString()); +} + +// Get rid of the script name +array_shift($_SERVER['argv']); +$tables = array_values($_SERVER['argv']); + +$xml = $manager->dumpSchema($tables); +if (is_a($xml, 'PEAR_Error')) { + $cli->fatal($xml->toString()); +} + +echo $xml; +exit(0); diff --git a/framework/admintools/horde-db-updatedata.php b/framework/admintools/horde-db-updatedata.php new file mode 100755 index 000000000..da39bcc62 --- /dev/null +++ b/framework/admintools/horde-db-updatedata.php @@ -0,0 +1,53 @@ +#!@php_bin@ + + * @category Horde + * @package admintools + */ + +// Do CLI checks and environment setup first. +require_once dirname(__FILE__) . '/horde-base.php'; +require_once $horde_base . '/lib/core.php'; + +// Make sure no one runs this from the web. +if (!Horde_Cli::runningFromCLI()) { + exit("Must be run from the command line\n"); +} + +// Load the CLI environment - make sure there's no time limit, init +// some variables, etc. +$cli = Horde_Cli::singleton(); +$cli->init(); + +// Include needed libraries. +$horde_authentication = 'none'; +require_once HORDE_BASE . '/lib/base.php'; + +$manager = Horde_SQL_Manager::getInstance(); +if (is_a($manager, 'PEAR_Error')) { + $cli->fatal($manager->toString()); +} + +// Get arguments. +array_shift($_SERVER['argv']); +if (!count($_SERVER['argv'])) { + exit("You must specify the data file to update.\n"); +} +$file = array_shift($_SERVER['argv']); +$debug = count($_SERVER['argv']) && array_shift($_SERVER['argv']) == 'debug'; + +$result = $manager->updateData($file, $debug); +if (is_a($result, 'PEAR_Error')) { + $cli->fatal('Failed to update database data: ' . $result->toString()); + exit(1); +} elseif ($debug) { + echo $result; +} else { + $cli->message('Successfully updated the database with data from "' . $file . '".', 'cli.success'); +} +exit(0); diff --git a/framework/admintools/horde-db-updateschema.php b/framework/admintools/horde-db-updateschema.php new file mode 100755 index 000000000..68d95c2ea --- /dev/null +++ b/framework/admintools/horde-db-updateschema.php @@ -0,0 +1,53 @@ +#!@php_bin@ + + * @category Horde + * @package admintools + */ + +// Do CLI checks and environment setup first. +require_once dirname(__FILE__) . '/horde-base.php'; +require_once $horde_base . '/lib/core.php'; + +// Make sure no one runs this from the web. +if (!Horde_Cli::runningFromCLI()) { + exit("Must be run from the command line\n"); +} + +// Load the CLI environment - make sure there's no time limit, init +// some variables, etc. +$cli = Horde_Cli::singleton(); +$cli->init(); + +// Include needed libraries. +$horde_authentication = 'none'; +require_once HORDE_BASE . '/lib/base.php'; + +$manager = Horde_SQL_Manager::getInstance(); +if (is_a($manager, 'PEAR_Error')) { + $cli->fatal($manager->toString()); +} + +// Get arguments. +array_shift($_SERVER['argv']); +if (!count($_SERVER['argv'])) { + exit("You must specify the schema file to update.\n"); +} +$file = array_shift($_SERVER['argv']); +$debug = count($_SERVER['argv']) && array_shift($_SERVER['argv']) == 'debug'; + +$result = $manager->updateSchema($file, $debug); +if (is_a($result, 'PEAR_Error')) { + $cli->fatal('Failed to update database definitions: ' . $result->toString()); + exit(1); +} elseif ($debug) { + echo $result; +} else { + $cli->message('Successfully updated the database with definitions from "' . $file . '".', 'cli.success'); +} +exit(0); diff --git a/framework/admintools/horde-remove-pref.php b/framework/admintools/horde-remove-pref.php new file mode 100755 index 000000000..6f0e02560 --- /dev/null +++ b/framework/admintools/horde-remove-pref.php @@ -0,0 +1,77 @@ +#!@php_bin@ +init(); + +$horde_authentication = 'none'; +$horde_no_compress = true; +require_once HORDE_BASE . '/lib/base.php'; + +$scope = $cli->prompt(_("Enter value for pref_scope:")); +$name = $cli->prompt(_("Enter value for pref_name:")); + +/* Open the database. */ +$db = DB::connect($conf['sql']); +if (is_a($db, 'PEAR_Error')) { + var_dump($db); + exit; +} + +// Set DB portability options. +switch ($db->phptype) { +case 'mssql': + $db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM); + break; +default: + $db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS); +} + +if ($live) { + $sql = 'DELETE FROM horde_prefs WHERE pref_scope = ? AND pref_name = ?'; + $values = array($scope, $name); + $result = $db->getAll($sql, $values); + if (is_a($result, 'PEAR_Error')) { + var_dump($result); + } elseif (empty($result)) { + $cli->writeln(sprintf(_("No preference \"%s\" found in scope \"%s\"."), $name, $scope)); + } else { + $cli->writeln(sprintf(_("Preferences \"%s\" deleted in scope \"%s\"."), $name, $scope)); + } +} else { + $sql = 'SELECT * FROM horde_prefs WHERE pref_scope = ? AND pref_name = ?'; + $values = array($scope, $name); + $result = $db->getAll($sql, $values); + if (empty($result)) { + $cli->writeln(sprintf(_("No preference \"%s\" found in scope \"%s\"."), $name, $scope)); + } else { + var_dump($result); + } +} diff --git a/framework/admintools/horde-sql-shell.php b/framework/admintools/horde-sql-shell.php new file mode 100755 index 000000000..d2cc3974c --- /dev/null +++ b/framework/admintools/horde-sql-shell.php @@ -0,0 +1,55 @@ +#!@php_bin@ + + */ + +// Do CLI checks and environment setup first. +require_once dirname(__FILE__) . '/horde-base.php'; +require_once $horde_base . '/lib/core.php'; + +// Make sure no one runs this from the web. +if (!Horde_Cli::runningFromCLI()) { + exit("Must be run from the command line\n"); +} + +// Load the CLI environment - make sure there's no time limit, init some +// variables, etc. +Horde_Cli::init(); + +// Include needed libraries. +$horde_authentication = 'none'; +require_once HORDE_BASE . '/lib/base.php'; + +$dbh = DB::connect($conf['sql']); +if (is_a($dbh, 'PEAR_Error')) { + throw new Horde_Exception($dbh); +} +$dbh->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS); + +// list databases command +// $result = $dbh->getListOf('databases'); + +// list tables command +// $result = $dbh->getListOf('tables'); + +// read sql file for statements to run +$statements = new Horde_Db_StatementParser($_SERVER['argv'][1]); +foreach ($statements as $stmt) { + echo "Running:\n " . preg_replace('/\s+/', ' ', $stmt) . "\n"; + $result = $dbh->query($stmt); + if (is_a($result, 'PEAR_Error')) { + var_dump($result); + exit; + } + + echo " ...done\n\n"; +} diff --git a/framework/admintools/horde-update.sh b/framework/admintools/horde-update.sh new file mode 100755 index 000000000..d0421277b --- /dev/null +++ b/framework/admintools/horde-update.sh @@ -0,0 +1,388 @@ +#!/bin/sh +# $Horde: framework/admintools/horde-update.sh,v 1.1 2006/09/11 05:01:14 chuck Exp $ +# +# update_horde.sh - Marcus I. Ryan +# +# I wrote this script for me, so there isn't really much documentation. +# I'll explain the few things that come to mind: +# +# Summary: This script facilitates the updating and/or installation of horde +# and its applications. +# * Create a temporary directory to hold a new install +# * Make a patch file of the various *.dist files and their non-dist versions +# * Copy the existing install or download fresh from CVS +# * Apply the patch made earlier +# * Make a backup of the existing install +# * Make the new download the current install +# +# Options/Variables: +# NUM_SLASHES - Since I'm too lazy to code a better way, this is the number +# of slashes to remove from the path to make the patch work +# relative to the temporary directory. +# NUM_BACKUPS - How many backups do we want to keep? +# WEBDIR - The actual install directory (this is the live version) +# BACKUPDIR - Where do we want to keep the backups +# TMPDIR - Where do we build the new version to install +# RELEASES - A list of the various "releases" we've defined +# _dir - The name of the "horde" dir (usually horde) for release +# _ver - A list of the various CVS distributions for realease +# and the CVS branches to download. See examples. +# +# WARNING: I do not currently have it set up to check if a patch fails +# completely. This is not usually a problem, but if a *.dist file +# is drastically updated it has been known to cause problems. +# If you use this script, please keep an eye out for this. That +# said, I updated both my installs (release and head) with it +# over 50 times before I finally had a problem. + +trim () { + echo $@ +} + +######## CONFIGURATION ######## + +### MISC. OPTIONS ### +NUM_SLASHES=4 +NUM_BACKUPS=5 + +### DIRECTORIES ### +WEBDIR=/usr/local/www +BACKUPDIR=/usr/local/src +TMPDIR=/usr/local/src + +### RELEASES ### +RELEASES="release head" + +# For each release, we need _dir and _ver settings + +#This is the "array" of applications and versions to get +release_dir=horde +release_ver=" + horde-RELENG_2 + imp-RELENG_3 + turba-RELENG_1 + kronolith-RELENG_1 + nag-RELENG_1 + mnemo-RELENG_1 +" +release_ver=`trim ${release_ver}` + +head_dir=horde.head +head_ver=" + horde-HEAD + framework-HEAD + imp-HEAD + turba-HEAD + gollem-HEAD + kronolith-HEAD + jonah-HEAD + troll-HEAD + nag-HEAD + nic-HEAD + mnemo-HEAD + passwd-HEAD + sam-HEAD +" +head_ver=`trim ${head_ver}` + +######## MAIN CODE ######## + +APPVER=$head_ver +HORDEDIR=$head_dir + +# check to see if any command line args are specified +for arg in $* +do + name=${arg%%=*} + name=${name##--} + value=${arg##*=} + if [ "$name" = "release" ]; then + APPVER=`eval echo '$'$value'_ver'` + HORDEDIR=`eval echo '$'$value'_dir'` + if [ "$APPVER" = "" -o "$HORDEDIR" = "" ]; then + echo "ERROR: No settings for release $value" + fi + continue + fi + echo "Unknown option $arg ('$name' = '$value')" + exit 1 +done + +echo "Verifying distribution list" +if [ ! "${APPVER%%[- ]*}" = "horde" ]; then + echo " horde MUST be the first item in the APPVER list!" + exit 1 +fi + +echo "Determining temporary directory..." +EXISTS=`ls -d ${TMPDIR}/${HORDEDIR}.TMP.[0-9]* | head -1` +TMPDIR="${TMPDIR}/${HORDEDIR}.TMP.$$" + +if [ ! -z ${EXISTS} ]; then + echo " Found an existing (aborted?) update of horde (${EXISTS})." + read -p " Should I use it? [Yes]" USE_EXISTING + case ${USE_EXISTING} in + [Nn]|[Nn][Oo]) + read -p " Should I delete ${EXISTS}? [Yes]" DELETE_EXISTING + case ${DELETE_EXISTING} in + [Nn]|[Nn][Oo]) + echo " Not deleting ${EXISTS}" + ;; + *) + echo " Deleting ${EXISTS}" + rm -rf ${EXISTS} + ;; + esac + ;; + *) + TMPDIR=${EXISTS} + ;; + esac + unset USE_EXISTING +fi +if [ -e ${TMPDIR} ]; then + echo " Using ${TMPDIR}" +else + echo " Creating new directory ${TMPDIR}" + mkdir ${TMPDIR} + if [ ! -e ${TMPDIR} ]; then + echo "ERROR: Couldn't create ${TMPDIR}" + exit 1 + fi +fi + +echo "Creating config patch file from existing horde" +if [ -e ${TMPDIR}/update.patch ]; then + read -p " This directory includes a patch. Use it? [Yes]" USE_EXISTING + case ${USE_EXISTING} in + [Nn]|[Nn][Oo]) + echo " Clearing existing update.patch" + rm -f ${TMPDIR}/update.patch || exit 1 + ;; + esac + unset USE_EXISTING +fi +if [ ! -e ${TMPDIR}/update.patch ]; then + if [ ! -e ${WEBDIR}/${HORDEDIR} ]; then + echo " No existing horde distribution found. Can't create patch." + else + read -p " Do you want to create a patch from the existing install? [Yes]" MAKE_PATCH + case ${MAKE_PATCH} in + [Nn]|[Nn][Oo]) + echo " Not creating a patch" + ;; + *) + echo " Creating patch...this could take a bit..." + find ${WEBDIR}/${HORDEDIR} -type f -name \*.dist -print \ + | perl -ne 's/\.dist[\r\n]*//; print "$_.dist\n$_\n";' \ + | xargs -n 2 diff -u > ${TMPDIR}/update.patch + ;; + esac + unset MAKE_PATCH + fi +fi + +if [ -e "${WEBDIR}/${HORDEDIR}" ]; then + read -p "Do you want to fetch new (N) or update (U)? [U] " FETCH_NEW +else + FETCH_NEW=new +fi + +case ${FETCH_NEW} in + [Nn]|[Nn][Ee][Ww]) + for APP in ${APPVER} + { + app=${APP%%-*} + rel=${APP##*-} + if [ ${app} = ${APP} ]; then + echo " No release specified...assuming HEAD" + rel=HEAD + fi + + case ${app} in + horde) + APPDIR=${TMPDIR} + EXISTDIR="${TMPDIR}/${HORDEDIR}" + ;; + *) + APPDIR=${TMPDIR}/${HORDEDIR} + EXISTDIR="${TMPDIR}/${HORDEDIR}/${app}" + ;; + esac + + if [ -e $EXISTDIR ]; then + case ${REGET} in + [Aa]|[Aa][Ll][Ll]) + echo " Removing existing ${APPDIR}/${app}..."; + rm -rf ${APPDIR}/${app} + echo " Retrieving ${app} $rel..." + cd ${APPDIR} + cvs -Q -z3 -d :pserver:cvsread@anoncvs.horde.org:/repository co \ + -r $rel ${app} + ;; + [Nn][Oo][Nn][Ee]) + REGET="NONE" + echo " Using existing ${APPDIR}/${app}" + ;; + *) + echo " ${app} exists. Should I get ${app} anyway?" + if [ "${app}" = "horde" ]; then + echo " NOTE: regetting horde does not clear out any existing files" + fi + read -p " [Y]es/[N]o/[A]ll/None (default None): " REGET + case ${REGET} in + [Yy]|[Yy][Ee][Ss]|[Aa]|[Aa][Ll][Ll]) + echo " Removing existing ${APPDIR}/${app}..."; + rm -rf ${APPDIR}/${app} + echo " Retrieving ${app} $rel..." + cd ${APPDIR} + cvs -Q -z3 -d :pserver:cvsread@anoncvs.horde.org:/repository co \ + -r $rel ${app} + ;; + [Nn]|[Nn][Oo]) + echo " Using existing ${APPDIR}/${app}" + ;; + *) + echo " Using existing ${APPDIR}/${app}" + REGET=NONE + ;; + esac + ;; + esac + else + echo -n " Retrieving ${app} $rel..." + cd ${APPDIR} + cvs -Q -z3 -d :pserver:cvsread@anoncvs.horde.org:/repository co \ + -r $rel ${app} + echo "done" + fi + if [ "$app" = "horde" -a "$HORDEDIR" != "horde" ]; then + echo " Moving ${TMPDIR}/horde to ${TMPDIR}/${HORDEDIR}" + mv ${TMPDIR}/horde ${TMPDIR}/${HORDEDIR} + fi + } + ;; + *) + mkdir ${TMPDIR}/${HORDEDIR} + cp -Rpf ${WEBDIR}/${HORDEDIR}/* ${TMPDIR}/${HORDEDIR} + cd ${TMPDIR}/${HORDEDIR} + cvs update -PdC + ;; +esac + +echo "Putting default config files in place..." +if [ -e ${TMPDIR}/${HORDEDIR}/config/conf.php ]; then + echo " I have found some configuration files already in place." + echo " If you are updating an existing installation this is normal." + echo " NOTE: If some have been copied and others not, horde will be broken." + read -p " Should I copy .dist files anyway? [Yes] " USE_EXISTING + #The phrasing of the question means USE_EXISTING from the read is backwards + # but it seems better to confuse the programmer than the user... + case ${USE_EXISTING} in + [Nn]|[Nn][Oo]) + USE_EXISTING=YES + ;; + *) + USE_EXISTING=NO + ;; + esac +fi +if [ "${USE_EXISTING:=NO}" = "NO" ]; then + echo " Copying *.dist files..." + find ${TMPDIR}/${HORDEDIR} -type f -name \*.dist -print \ + | perl -ne 'print "$_"; s/\.dist//; print "$_"' \ + | xargs -n 2 cp +fi + +echo "Applying patch..." +echo " Clearing out any old reject files..." +find ${TMPDIR} -name \*.rej -type f -exec rm {} \; -print + +if [ ! -e ${TMPDIR}/update.patch ]; then + echo " I can't seem to find the patch file ${TMPDIR}/update.patch!" + read -p " Do you want me to load all config files in $EDITOR? [No]" EDIT + case ${EDIT} in + [Yy]|[Yy][Ee][Ss]) + find ${TMPDIR}/${HORDEDIR} -type f -name \*.dist \ + | perl -ne 's/\.dist[\r\n]*//; print "$_\n";' \ + | xargs -n 2 echo $EDITOR > ${TMPDIR}/edit.sh + sh ${TMPDIR}/edit.sh + rm ${TMPDIR}/edit.sh + ;; + *) + echo " WARNING: You need to change the config files later!" + ;; + esac +else + if [ "${USE_EXISTING}" = "YES" ]; then + echo " We kept the modified configuration files." + read -p " Should we still apply the patch? [No] " PATCH + case ${PATCH} in + [Yy]|[Yy][Ee][Ss]) + PATCH=YES + ;; + *) + PATCH=NO + ;; + esac + fi + + if [ "${PATCH:=YES}" = "YES" ]; then + echo " running patch" + cd ${TMPDIR} + if [ `patch -f -p${NUM_SLASHES} -s < ${TMPDIR}/update.patch` ]; then + echo " Patch applied successfully" + else + find ${TMPDIR}/${HORDEDIR} -type f -name \*.rej \ + | perl -ne 's/\.rej[\r\n]*//; print "$_.rej\n$_\n"; ' \ + | xargs -n 2 echo $EDITOR > ${TMPDIR}/edit.sh + sh ${TMPDIR}/edit.sh + rm ${TMPDIR}/edit.sh + fi + fi +fi + +read -p "Are you ready to put the new CVS into production? [Yes]" PROD +case ${PROD} in +[Nn]|[Nn][Oo]) + echo "${TMPDIR} has not been put in production." + ;; +*) + if [ -e ${WEBDIR}/${HORDEDIR} ]; then + i=1 + while [ ${i} != ${NUM_BACKUPS} ] + do + if [ ! -e ${BACKUPDIR}/${HORDEDIR}.${i} ]; then + break; + fi + i=$((${i}+1)) + done + + if [ ${i} = ${NUM_BACKUPS} ] && [ -e ${BACKUPDIR}/${HORDEDIR}.${i} ]; then + echo " Removing oldest backup directory (${BACKUPDIR}/${HORDEDIR}.${i})" + rm -rf ${BACKUPDIR}/${HORDEDIR}.${i} || exit 1 + fi + + while [ ${i} != 1 ] + do + echo " Moving ${BACKUPDIR}/${HORDEDIR}.$((${i}-1)) to ${BACKUPDIR}/${HORDEDIR}.${i}" + mv ${BACKUPDIR}/${HORDEDIR}.$((${i}-1)) ${BACKUPDIR}/${HORDEDIR}.${i} || exit 1 + i=$((${i}-1)) + done + + echo " Moving ${WEBDIR}/${HORDEDIR} to ${BACKUPDIR}/${HORDEDIR}.1" + mv ${WEBDIR}/${HORDEDIR} ${BACKUPDIR}/${HORDEDIR}.1 || exit 1 + + echo " Moving ${TMPDIR}/${HORDEDIR} ${WEBDIR}/${HORDEDIR}" + mv ${TMPDIR}/${HORDEDIR} ${WEBDIR}/${HORDEDIR} || exit 1 + + echo " Removing ${TMPDIR}" + rm -rf ${TMPDIR} + + echo "New CVS horde is now in production!" + else + echo "${WEBDIR}/${HORDEDIR} does not exist. Copying ${TMPDIR}/${HORDEDIR} to ${WEBDIR}/${HORDEDIR}" + cp ${TMPDIR}/${HORDEDIR} ${WEBDIR}/${HORDEDIR} + fi + ;; +esac diff --git a/framework/admintools/package.xml b/framework/admintools/package.xml new file mode 100644 index 000000000..9e77024ba --- /dev/null +++ b/framework/admintools/package.xml @@ -0,0 +1,103 @@ + + + admintools + pear.horde.org + Horde Administrator Tools + This package contains scripts useful to people administering Horde installations. + + + Chuck Hagenbuch + chuck + chuck@horde.org + yes + + + Jan Schneider + jan + jan@horde.org + yes + + 2009-12-22 + + 0.3.0 + 0.3.0 + + + beta + beta + + LGPL + * Initial Horde 4 package. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5.2.0 + + + 1.7.0 + + + + + + + + + + + + + + + + + + + 2008-06-24 + + 0.2.0 + 0.2.0 + + + beta + beta + + LGPL + - Add a script for creating PEAR::DB sequences + - Add scripts for dumping and updating the Horde database from MDB2_Schema XML files + - Add a script for running a series of SQL statements from STDIN on the Horde database + - Add scripts for dumping and restoring data from the Horde database + + + + diff --git a/framework/devtools/README b/framework/devtools/README new file mode 100644 index 000000000..773d414b8 --- /dev/null +++ b/framework/devtools/README @@ -0,0 +1,29 @@ +===================== +Horde Developer Tools +===================== + +Introduction +~~~~~~~~~~~~ +This directory contains various developer scripts for the Horde +distribution. + + +Script Index +~~~~~~~~~~~~ +horde-check-themes.php + Makes sure that themes that provide their own images aren't missing any. + +horde-fw-symlinks.php + Creates symbolic links necessary for developers to work directly on the + files in the framework module without needing to install the changed + packages. + +horde-highlight.php + Highlights source files on the console. + +horde-merge.php + Merges commits from a commit message into the CVS tree of the current + directory. + +horde-rev-cmp.sh + Compares different CVS revisions of the same file. diff --git a/framework/devtools/horde-check-themes.php b/framework/devtools/horde-check-themes.php new file mode 100755 index 000000000..0915a4e59 --- /dev/null +++ b/framework/devtools/horde-check-themes.php @@ -0,0 +1,203 @@ +#!@php_bin@ + + */ + +/* CLI checks and environment setup first. */ +require_once 'Horde/Cli.php'; + +/* Make sure no one runs this from the web. */ +if (!Horde_Cli::runningFromCLI()) { + exit("Must be run from the command line\n"); +} + +/* Get any options. */ +$simple = false; +$horde_base = null; +$ignore = array(); +if (isset($argv)) { + /* Get rid of the first arg which is the script name. */ + array_shift($argv); + while ($arg = array_shift($argv)) { + if ($arg == '--help') { + print_usage(); + } elseif ($arg == '-s') { + $simple = true; + } elseif (strpos($arg, '-i') === 0) { + list(,$ignore[]) = explode('=', $arg); + } elseif (file_exists($arg . '/config/registry.php')) { + $horde_base = $arg; + } else { + print_usage("Unrecognised option $arg"); + } + } +} + +if ($horde_base === null) { + print_usage("You must specify the base path to Horde."); +} + +/* Set up CLI. */ +$cli = Horde_Cli::singleton(); +$cli->init(); + +$horde_authentication = 'none'; +require_once $horde_base . '/lib/base.php'; + +/* Get the apps and start doing checks. */ +$apps = $registry->listApps(array('hidden', 'notoolbar', 'active', 'admin')); + +/* Get a list of themes. */ +$themes = array(); +$themes_dir = $registry->get('themesfs', 'horde'); +if ($handle = opendir($themes_dir)) { + while ($file = readdir($handle)) { + if ($file == '.' || $file == '..' || $file == 'CVS' || + $file == '.svn' || + !file_exists("$themes_dir/$file/themed_graphics") || + !file_exists("$themes_dir/$file/graphics")) { + continue; + } + + /* Store the apps and their theme directories. */ + foreach ($apps as $app) { + $dir = $registry->get('themesfs', $app) . '/' . $file . '/graphics'; + if (is_dir($dir)) { + $themes[$app][$file] = $dir; + } + } + } +} + +foreach ($apps as $app) { + /* Skip applications without icon themes. */ + if (!isset($themes[$app])) { + continue; + } + + /* Set up some dirs. */ + $themes_dir = $registry->get('themesfs', $app); + $horde_icon_dir = $themes_dir . '/graphics'; + + /* Sanity check for the directories. */ + if (!file_exists($horde_icon_dir)) { + continue; + } + + /* Get a list of all horde images recursively. */ + $horde_icon_list = array(); + readDirRecursively($horde_icon_dir, $horde_icon_dir, $horde_icon_list); + + /* Loop through themes that replace icons and check for differences. */ + foreach ($themes[$app] as $theme => $theme_icon_dir) { + $theme_icon_list = array(); + readDirRecursively($theme_icon_dir, $theme_icon_dir, $theme_icon_list); + + /* Check for icons that are in the Horde base theme and not in the + * custom theme. */ + $diff = array_diff($horde_icon_list, $theme_icon_list); + /* Don't bother reporting anything for themes that have all the horde + * base icons. */ + if (empty($diff)) { + continue; + } + + $cli->writeln($cli->red(sprintf('[%s] "%s" theme missing these icons:', + strtoupper($app), + $theme))); + sort($diff); + foreach ($diff as $icon) { + $cli->writeln($icon); + } + + /* Check if only doing a Horde base theme to custom theme check. Skip + * the reverse checking if true. */ + if ($simple) { + continue; + } + + /* Check for icons that are in the Horde base theme and not in the + * custom theme. */ + $diff = array_diff($theme_icon_list, $horde_icon_list); + /* Don't bother reporting anything for themes that don't have any icons + * more than the base theme. */ + if (empty($diff)) { + continue; + } + + $cli->writeln($cli->blue(sprintf('[%s] "%s" theme has these extra icons:', + strtoupper($app), + $theme))); + sort($diff); + foreach ($diff as $icon) { + $cli->writeln($icon); + } + } +} + +$cli->writeln($cli->green('Done.')); +exit; + +/** + * Loops through the directory recursively and stores the found + * graphics into an array. + */ +function readDirRecursively($path, $basepath, &$list) +{ + global $ignore; + + if ($handle = opendir($path)) { + while ($file = readdir($handle)) { + if ($file == '.' || $file == '..' || + $file == 'CVS' || $file == '.svn') { + continue; + } + if (is_dir("$path/$file")) { + readDirRecursively("$path/$file", $basepath, $list); + } else { + foreach ($ignore as $pattern) { + if (preg_match($pattern, $file)) { + continue 2; + } + } + $list[] = substr($path, strlen($basepath)) . "/$file"; + } + } + closedir($handle); + } + +} + +function print_usage($message = '') +{ + + if (!empty($message)) { + print "themes_check.php: $message\n\n"; + } + + print << + * Copyright 2003-2009 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Horde + * @package devtools + * @author Wolfram Kriesing + * @author Jan Schneider + */ + +// Default values for srcDir and destDir are empty. +$srcDir = null; +$destDir = null; + +// Default to copying if this is run on Windows. +$copy = strncasecmp(PHP_OS, 'WIN', 3) ? false : true; + +// All packages by default. +$pkg = null; + +for ($i = 1; $i < count($argv); $i++) { + switch ($argv[$i]) { + case '--copy': + $copy = true; + break; + + case '--help': + print_usage(); + + case '--src': + if (isset($argv[$i + 1])) { + if (is_dir($argv[$i + 1])) { + $srcDir = $argv[$i + 1]; + $i++; + } else { + exit($argv[$i + 1] . " is not a directory"); + } + } + break; + + case '--dest': + if (isset($argv[$i + 1])) { + if (is_dir($argv[$i + 1])) { + $destDir = $argv[$i + 1]; + $i++; + } else { + exit($argv[$i + 1] . " is not a directory"); + } + } + break; + + case '--pkg': + $pkg = $argv[$i + 1]; + if (!is_dir($pkg) || !file_exists($pkg . '/package.xml')) { + exit("$pkg is not a valid package directory.\n"); + } + $pkg = preg_replace('|/+$|', '', $pkg); + $i++; + break; + + default: + print_usage("Unrecognised option $argv[$i]"); + } +} + +// Try to auto-detect the source and dest dirs. +$cwd = getcwd(); +if ($srcDir === null && is_dir($cwd . DIRECTORY_SEPARATOR . 'framework')) { + $srcDir = $cwd . DIRECTORY_SEPARATOR . 'framework'; +} +if ($destDir === null && is_dir($cwd . DIRECTORY_SEPARATOR . 'libs')) { + $destDir = $cwd . DIRECTORY_SEPARATOR . 'libs'; +} + +if ($srcDir === null || $destDir === null) { + print_usage('Failed to auto-detect source and destination directories,'); +} + +// Make $srcDir an absolute path. +if (($srcDir[0] != '/' && !preg_match('/[A-Za-z]:/', $srcDir)) && + $cwd = getcwd()) { + $srcDir = $cwd . '/' . $srcDir; +} +$srcDir = rtrim($srcDir, '/'); + +// Make $destDir an absolute path. +if (($destDir[0] != '/' && !preg_match('/[A-Za-z]:/', $destDir)) && + $cwd = getcwd()) { + $destDir = $cwd . '/' . $destDir; +} +$destDir = rtrim($destDir, '/'); + +// Put $destDir into include_path. +if (strpos(ini_get('include_path'), $destDir) === false) { + ini_set('include_path', $destDir . PATH_SEPARATOR . ini_get('include_path')); +} + +// Do CLI checks and environment setup first. +if (!@include_once 'Horde/Cli.php') { + if (!@include_once $srcDir . '/Cli/lib/Horde/Cli.php') { + if (!@include_once $cwd . DIRECTORY_SEPARATOR . 'framework/Cli/lib/Horde/Cli.php') { + print_usage('Horde_Cli library is not in the include_path or in the src directory.'); + } + } +} + +// Make sure no one runs this from the web. +if (!Horde_Cli::runningFromCLI()) { + exit; +} + +// Load the CLI environment - make sure there's no time limit, init +// some variables, etc. +Horde_Cli::init(); + +if (!class_exists('SimpleXMLElement', false)) { + include_once 'Tree/Tree.php'; + if (!class_exists('Tree')) { + print_usage('You need the PEAR "Tree" package installed'); + } +} + +// Tree throws some irrelevant reference; silence them. +error_reporting(E_ALL & ~E_NOTICE); + +$linker = new Linker($copy); +if ($pkg) { + $linker->process(getcwd() . DIRECTORY_SEPARATOR . $pkg, $destDir); +} elseif ($handle = opendir($srcDir)) { + while ($file = readdir($handle)) { + if ($file != '.' && + $file != '..' && + $file != 'CVS' && + is_dir($srcDir . '/' . $file)) { + $linker->process($srcDir . '/' . $file, $destDir); + } + } + closedir($handle); + } + +echo "\n"; + +/** + */ +class Linker { + + var $_srcDir; + + /** + * The base directory for the complete package. + * + * @string + */ + var $_baseDir; + + /** + * The base installation directories of the current directory or file + * relative to $_baseDir. The current base directory is always at array + * position 0. + * + * @array + */ + var $_baseInstallDir = array(''); + + var $_fileroles = array('php'); + + var $_role; + + var $_copy; + + var $_tree; + + var $_contents; + + function Linker($copy = false) + { + $this->_copy = $copy; + } + + function process($srcDir, $destDir) + { + $this->_srcDir = $srcDir; + $packageFile = $this->_srcDir . '/package.xml'; + $cli = &Horde_Cli::singleton(); + + if (!is_file($packageFile)) { + $cli->message('No package.xml in ' . $this->_srcDir, 'cli.warning'); + return false; + } + + $this->_tree = $this->getXmlTree($packageFile); + + // Read package name. + $packageName = trim($this->_tree->getElementContent('/package/name', 'cdata')); + $cli->writeln("Processing package $packageName."); + + // First, look for '/package/phprelease/filelist', which + // overrides '/package/contents'. + if (($filelist = $this->_tree->getElementByPath('/package/phprelease/filelist'))) { + // Do this better, make the tree class work case insensitive. + $this->_baseDir = preg_replace('|/+|', '/', $destDir); + if (!is_dir($this->_baseDir)) { + require_once 'System.php'; + System::mkdir('-p ' . $this->_baseDir); + } + + $this->_handleFilelistTag($filelist); + + // Look for contents in '/package/contents'. + } elseif (($this->_contents = $this->_tree->getElementByPath('/package/contents'))) { + // Do this better, make the tree class work case insensitive. + $this->_baseDir = preg_replace('|/+|', '/', $destDir); + if (!is_dir($this->_baseDir)) { + require_once 'System.php'; + System::mkdir('-p ' . $this->_baseDir); + } + + $this->_handleContentsTag($this->_contents); + + // Didn't find either. + } else { + $cli->message('No filelist or contents tags found inside: ' . $packageFile, 'cli.warning'); + } + + unset($this->_tree); + unset($this->_contents); + } + + function _handleFilelistTag($element, $curDir = '') + { + if (isset($element['children'])) { + foreach ($element['children'] as $child) { + switch ($child['name']) { + case 'install': + // + $this->_handleInstallTag($child, $curDir); + break; + + default: + $cli = &Horde_Cli::singleton(); + $cli->message('No handler for tag: ' . $child['name'], 'cli-warning'); + break; + } + } + } + } + + function _handleContentsTag($element, $curDir = '') + { + if (isset($element['children'])) { + foreach ($element['children'] as $child) { + switch ($child['name']) { + case 'file': + $this->_handleFileTag($child, $curDir); + break; + + case 'dir': + $this->_handleDirTag($child, $curDir); + break; + + default: + $cli = &Horde_Cli::singleton(); + $cli->message('No handler for tag: ' . $child['name'], 'cli-warning'); + break; + } + } + } + } + + function _handleDirTag($element, $curDir) + { + if ($element['attributes']['name'] != '/') { + if (substr($curDir, -1) != DIRECTORY_SEPARATOR) { + $curDir .= DIRECTORY_SEPARATOR; + } + $curDir .= $element['attributes']['name']; + } + + if (!empty($element['attributes']['baseinstalldir'])) { + array_unshift($this->_baseInstallDir, $element['attributes']['baseinstalldir']); + } + $this->_handleContentsTag($element, $curDir); + if (!empty($element['attributes']['baseinstalldir'])) { + array_shift($this->_baseInstallDir); + } + } + + function _handleFileTag($element, $curDir) + { + if (!empty($element['attributes']['role'])) { + $this->_role = $element['attributes']['role']; + } + + if (!in_array($this->_role, $this->_fileroles)) { + return; + } + + if (!empty($element['attributes']['name'])) { + $filename = $element['attributes']['name']; + } else { + $filename = $element['cdata']; + } + $filename = trim($filename); + + if (!empty($element['attributes']['baseinstalldir'])) { + $dir = $element['attributes']['baseinstalldir']; + } else { + $dir = $this->_baseInstallDir[0]; + } + if (substr($dir, -1) == '/') { + $dir = substr($dir, 0, -1); + } + $dir .= $curDir; + if (substr($dir, -1) == '/') { + $dir = substr($dir, 0, -1); + } + + if (!is_dir($this->_baseDir . $dir)) { + require_once 'System.php'; + System::mkdir('-p ' . $this->_baseDir . $dir); + } + + if ($this->_copy) { + $cmd = "cp {$this->_srcDir}$curDir/$filename {$this->_baseDir}$dir/$filename"; + } else { + $parent = $this->_findCommonParent($this->_srcDir . $curDir, + $this->_baseDir . $dir); + $dirs = substr_count(substr($this->_baseDir . $dir, + strlen($parent)), + '/'); + $src = str_repeat('../', $dirs) . + substr($this->_srcDir . $curDir, strlen($parent) + 1); + $cmd = "ln -sf $src/$filename {$this->_baseDir}$dir/$filename"; + } + + exec($cmd); + } + + function _handleInstallTag($element, $curDir) + { + if (empty($element['attributes']['name'])) { + // Warning? + return; + } + $src = trim($element['attributes']['name']); + $srcDir = dirname($src); + + if (empty($element['attributes']['as'])) { + // Warning? + return; + } + $as = trim($element['attributes']['as']); + $asDir = dirname($as); + + $role = $this->_findRole($src); + if (!in_array($role, $this->_fileroles)) { + return; + } + + if (!is_dir($this->_baseDir . '/' . $asDir)) { + require_once 'System.php'; + System::mkdir('-p ' . $this->_baseDir . '/' . $asDir); + } + + if ($this->_copy) { + $cmd = "cp {$this->_srcDir}$curDir/$src {$this->_baseDir}/$as"; + } else { + $parent = $this->_findCommonParent($this->_srcDir . $curDir, + $this->_baseDir . $asDir); + $dirs = substr_count(substr($this->_baseDir . $srcDir, strlen($parent)), + '/'); + $src = str_repeat('../', $dirs) . substr($this->_srcDir . $curDir, strlen($parent) + 1) . '/' . $src; + $cmd = "ln -sf $src {$this->_baseDir}/$as"; + } + + exec($cmd); + } + + function _findRole($filename) + { + if (!$this->_contents) { + $this->_contents = $this->_tree->getElementByPath('/package/contents'); + if (!$this->_contents) { + return false; + } + } + + if (!isset($this->_contents['children'])) { + return false; + } + + $pieces = explode('/', $filename); + if (!count($pieces)) { + return false; + } + + $element = $this->_contents; + while (true) { + $continue = false; + foreach ($element['children'] as $child) { + if (!in_array($child['name'], array('file', 'dir'))) { + continue; + } + + if ($child['attributes']['name'] == '/') { + $continue = true; + break; + } + + if ($child['attributes']['name'] == $pieces[0]) { + if (count($pieces) == 1) { + if (isset($child['attributes']['role'])) { + return $child['attributes']['role']; + } else { + return false; + } + } + + array_shift($pieces); + if (!count($pieces)) { + return false; + } + + $continue = true; + break; + } + } + + if (!$continue) { + return false; + } + + if (!isset($child['children'])) { + return false; + } + $element = $child; + } + + return false; + } + + function _findCommonParent($a, $b) + { + for ($common = '', $lastpos = 0, $pos = strpos($a, '/', 1); + $pos !== false && strpos($b, substr($a, 0, $pos)) === 0; + $pos = strpos($a, '/', $pos + 1)) { + $common .= substr($a, $lastpos, $pos - $lastpos); + $lastpos = $pos; + } + return $common; + } + + function getXmlTree($packageFile) + { + if (class_exists('SimpleXMLElement', false)) { + return new Linker_Xml_Tree($packageFile); + } else { + $tree = Tree::setupMemory('XML', $packageFile); + $tree->setup(); + return $tree; + } + } + +} + +class Linker_Xml_Tree +{ + var $_sxml; + + function __construct($packageFile) + { + $this->_sxml = simplexml_load_file($packageFile); + } + + function getElementContent($path, $field) + { + $elt = $this->getElementByPath($path); + return $elt[$field]; + } + + function getElementByPath($path) + { + $path = str_replace('/package', '', $path); + + $node = $this->_sxml; + $path = preg_split('|/|', $path, -1, PREG_SPLIT_NO_EMPTY); + while ($path) { + $ptr = array_shift($path); + if (!$node->$ptr) return null; + $node = $node->$ptr; + } + + return $this->_asArray($node); + } + + function _asArray($sxml) + { + $element = array(); + $element['name'] = $sxml->getName(); + $element['cdata'] = (string)$sxml; + $element['attributes'] = array(); + foreach ($sxml->attributes() as $k => $v) { + $element['attributes'][$k] = (string)$v; + } + $element['children'] = array(); + foreach ($sxml->children() as $node) { + $element['children'][] = $this->_asArray($node); + } + + return $element; + } + +} + +function print_usage($message = '') +{ + + if (!empty($message)) { + echo "horde-fw-symlinks.php: $message\n\n"; + } + + echo << + */ + +if (!isset($argv[1])) { + echo "Usage: highlight.php SOURCE_FILE [HIGHLIGHTER]\n"; + exit; +} + +require_once 'Text/Highlighter.php'; +require_once 'Text/Highlighter/Renderer/Console.php'; + +/* File to highlight. */ +$file = $argv[1]; + +/* Optional highlighter. */ +if (isset($argv[2])) { + $type = $argv[2]; +} else { + /* Try autodetecting. */ + $map = array('cpp' => 'CPP', + 'css' => 'CSS', + 'diff' => 'DIFF', 'patch' => 'DIFF', + 'dtd' => 'DTD', + 'js' => 'JAVASCRIPT', + 'pl' => 'PERL', + 'php' => 'PHP', + 'py' => 'PYTHON', + 'sql' => 'SQL', + 'xml' => 'XML'); + $ext = strtolower(substr($file, strrpos($file, '.') + 1)); + if (isset($map[$ext])) { + $type = $map[$ext]; + } else { + $type = 'PHP'; + } +} + +$hl = Text_Highlighter::factory($type); +$hl->setRenderer(new Text_Highlighter_Renderer_Console()); + +echo $hl->highlight(file_get_contents($file)); diff --git a/framework/devtools/horde-merge.php b/framework/devtools/horde-merge.php new file mode 100755 index 000000000..aaf840343 --- /dev/null +++ b/framework/devtools/horde-merge.php @@ -0,0 +1,135 @@ +#!@php_bin@ + + * 2.485 +26 -5 imp/compose.php + * 1.503 +2 -0 imp/docs/CHANGES + * 2.159 +25 -12 imp/templates/compose/compose.inc + * 2.55 +28 -3 imp/templates/compose/javascript.inc + * + * from the standard input and merges these commits into the appropriate files + * of the current directory. Mainly for merging changes in HEAD to the RELENG + * tree. This script should be run from Horde's root. + * + * @category Horde + * @package devtools + */ + +// Location of the cvs binary +$CVS = 'cvs'; + +@set_time_limit(0); +ob_implicit_flush(true); +ini_set('track_errors', true); +ini_set('implicit_flush', true); +ini_set('html_errors', false); +ini_set('magic_quotes_runtime', false); + +$reverse = $join = $commit = $compress = false; +$target = '.'; +while ($arg = array_shift($argv)) { + switch ($arg) { + case '-R': + $reverse = true; + break; + case '-j': + $join = true; + break; + case '-c': + $commit = true; + break; + case '-z': + $compress = true; + break; + case '-t': + $target = array_shift($argv); + break; + } +} +$target .= '/'; + +$lines = array(); +while (!feof(STDIN)) { + $lines[] = fgets(STDIN); +} +foreach ($lines as $line) { + $line = trim($line); + if (empty($line)) { + continue; + } + $tok = preg_split('/\s+/', $line, -1, PREG_SPLIT_NO_EMPTY); + $file = str_replace(array('horde/', 'Attic/'), '', $tok[3]); + if (isset($tok[4]) && $tok[4] == '(dead)') { + $cmd = $CVS . ' remove -f ' . $file; + $new_version = $tok[0]; + } elseif (isset($tok[4]) && $tok[4] == '(new)') { + $cmd = ''; + $dir = dirname($file); + if (!is_dir($dir)) { + $cmd = "$CVS -f co $dir; "; + } + $cmd .= $CVS . ' up -j ' . $tok[0] . ' ' . $file; + $new_version = $tok[0]; + } else { + if (count($tok) != 4) { + print "Unknown line format:\n" . $line . "\n"; + continue; + } + $new_version = explode('.', $tok[0]); + $old_version = $new_version; + $old_version[count($old_version) - 1]--; + if ($old_version[count($old_version) - 1] == 0) { + unset($old_version[count($old_version) - 1]); + unset($old_version[count($old_version) - 1]); + } + $new_version = implode('.', $new_version); + $old_version = implode('.', $old_version); + if ($reverse) { + $tmp = $new_version; + $new_version = $old_version; + $old_version = $tmp; + } + if ($join) { + $cmd = sprintf($CVS . ' up -j %s -j %s -kk %s', + $old_version, + $new_version, + $file); + } else { + $cmd = sprintf($CVS . ' diff -N -r %s -r %s -kk %s | patch %s', + $old_version, + $new_version, + $file, + $target . $file); + } + } + print $cmd . "\n"; + system($cmd . ' 2>&1', $exit); + print "\n"; + + if ($exit !== 0) { + continue; + } + + // Compress JS files if necessary + if ($compress && $old_version && + preg_match('/^([^\/]+)\/(.+)\/(.+)$/', $file, $matches) && + $matches[2] == 'js/src') { + $currdir = getcwd(); + chdir(implode('/', array($matches[1], $matches[2]))); + passthru('php ' . $currdir . '/framework/devtools/horde-js-compress.php --file=' . $matches[3]); + chdir($currdir); + if ($commit) { + print "Commit doesn't work for compressed JS files - you need to commit manually.\n"; + } + } + + if ($commit) { + $cmd = sprintf($CVS . ' ci -m "%s: %s" %s', + $reverse ? 'Revert' : (substr_count($new_version, '.') > 1 ? 'MFB' : 'MFH'), + $reverse ? $old_version : $new_version, + $file); + print $cmd . "\n"; + system($cmd . ' 2>&1'); + } +} diff --git a/framework/devtools/horde-rev-cmp.sh b/framework/devtools/horde-rev-cmp.sh new file mode 100755 index 000000000..eae216766 --- /dev/null +++ b/framework/devtools/horde-rev-cmp.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# +# Script to compare revisions and ignore files that should be different, and +# differences in revision numbers. +# Syntax: ./compare_revisions.sh FIRST_FOLDER SECOND_FOLDER ['ADDITIONAL PARAMETERS'] + +FIRST=$1 +SECOND=$2 +shift 2 +diff -r -I "\$Horde" -I "\$Revision" -I "\$Date" -I "\$Id" --exclude version.php --exclude CHANGES --exclude CREDITS --exclude '*.po' --exclude '*.pot' --exclude locale --exclude CVS --exclude '.#*' --exclude '*~' --exclude '*.bak' --exclude '*.orig' --exclude '*.rej' "$@" $FIRST $SECOND | grep -v "config/.*\.php " diff --git a/framework/devtools/package.xml b/framework/devtools/package.xml new file mode 100644 index 000000000..5c75a6806 --- /dev/null +++ b/framework/devtools/package.xml @@ -0,0 +1,83 @@ + + + devtools + pear.horde.org + Horde Developer Tools + This package contains scripts useful to people doing Horde development. + + + Chuck Hagenbuch + chuck + chuck@horde.org + yes + + + Jan Schneider + jan + jan@horde.org + yes + + 2009-12-23 + + 0.2.0 + 0.2.0 + + + beta + beta + + LGPL + * Initial Horde 4 release. + + + + + + + + + + + + + + + + + + + 5.2.0 + + + 1.7.0 + + + + + + + + + + + + + + 2006-09-11 + + 0.2.0 + 0.2.0 + + + beta + beta + + LGPL + * Initial Horde 4 release. + + + +