<?php
/**
* phpMakeUpdate - web tool for make the updates from Subversion repository
* Copyright (C) 2006 Arthur Harder
*
* web: http://www.easyWebSolutions.biz or http://www.easyWebSolutions.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
class makeupdate
{
var $errors = array();
function __construct()
{
//
}
function makeupdate()
{
$this->__construct();
}
/**
* Execute the 'svnlook history' command
*
* @param string $path Path in repository (/trunk, /branches/myproject etc)
* @return boolean
*/
function get_history($path)
{
if ( substr($path,0,1) != '/' )
{
$path = '/'.$path;
}
$command = SVNLOOK.' history '.$_SESSION['repository'].' '.$path;
$result = $this->Execute($command);
if ( !empty($result[ID_ERROUT]) )
{
$this->command = $command;
$this->errors = $result[ID_ERROUT];
return false;
}
$erg = array();
foreach ($result[ID_STDOUT] as $line)
{
$line = trim($line);
$_arr = preg_split('/[\s]+/',$line);
if ((int) $_arr[0] > 0)
{
$foo = new foo;
$foo->revision = $_arr[0];
$foo->path = $_arr[1];
$erg[] = $foo;
}
}
$this->result = $erg;
return true;
}
/**
* Execute the 'svnlook info' command
*
* @param integer $revision Revision number in the repository
* @return boolean
*/
function get_info($revision)
{
if ( (int) $revision < 1 )
{
$revision = 1;
}
$command = SVNLOOK.sprintf(" info -r %d ".$_SESSION['repository'],$revision);
$result = $this->Execute($command);
if ( !empty($result[ID_ERROUT]) )
{
$this->errors = $result[ID_ERROUT];
return false;
}
$erg = array();
$erg[ID_AUTHOR] = $result[ID_STDOUT][0];
$erg[ID_DATE] = $result[ID_STDOUT][1];
$erg[ID_MESSAGE_SIZE] = $result[ID_STDOUT][2];
$erg[ID_MESSAGE] = $result[ID_STDOUT][3];
$this->result = $erg;
return true;
}
/**
* Get list with all changed files with svnlook changed -r
*
* All revision numbers are reading from $_SESSION['checkbox']
*
* @param string $path Path in repository (/trunk, /branches/myproject etc)
* @return boolean
*/
function get_changes($path)
{
$this->result = array();
$this->deleted_files = array();
$path = trim($path);
if (strlen($path) < 4 )
{
return false;
}
if ( substr($path,0,1) == '/' )
{
$path = substr($path,1);
}
if ( substr($path,-1,1) == '/' )
{
$path = substr($path,0,strlen($path)-1);
}
if ( !empty($_SESSION['checkbox']) && count($_SESSION['checkbox']) > 0 )
{
$arg = '';
ksort($_SESSION['checkbox']);
reset($_SESSION['checkbox']);
while ( $key = key($_SESSION['checkbox']) )
{
$arg .= ' ' . $key;
next($_SESSION['checkbox']);
}
$command = 'for i in'.$arg.'; do '.SVNLOOK.' changed -r $i '.$_SESSION['repository'].'; done';
$result = $this->Execute($command);
if ( !empty($result[ID_ERROUT]) )
{
$this->errors = $result[ID_ERROUT];
return false;
}
foreach ($result[ID_STDOUT] as $line)
{
$line = trim($line);
$_arr = preg_split('/[\s]+/',$line);
if ( count($_arr) > 1)
{
$pos = strpos($line,$path);
if ($pos === false || substr($_arr[1],strlen($path)+1) == '')
{
continue;
}
$foo = new foo;
$foo->filename = substr($_arr[1],strlen($path)+1);
$foo->status = $_arr[0];
if (strstr('D',$_arr[0]))
{
$this->deleted_files[$foo->filename] = $foo;
}
else
{
$this->result[$foo->filename] = $foo;
}
}
}
sort ($this->result);
reset($this->result);
sort($this->deleted_files);
reset($this->deleted_files);
}
return true;
}
/**
* Make the tarbal and send it into browser window
*
* @param string $repository Real Path to repository
* @param string $source Path in repository (/trunk, /branches/myproject etc)
* @param string $files_array only selected files from 'available files for update' list
* @return boolean
*/
function makeTar($source, $files_array)
{
if ( isset($_SESSION['repository']) )
{
$repository = $_SESSION['repository'];
}
else
{
return false;
}
$file = '';
if ( count($files_array) > 0 )
{
$arg = '';
foreach ($files_array as $file)
{
$arg .= ' '. $file;
}
if (strlen($source) < 4 || strlen($repository) < 4 )
{
return false;
}
if (substr($source,0,1) == '/')
{
$source = substr($source,1);
}
if (substr($repository,-1,1) != '/')
{
$repository .= '/';
}
chdir('tmp');
umask(0);
$command = 'umask 0; '.SVN.' export file://'.
$repository.$source.' update && chmod -R a+w update; cd update; mkdir UPDATE; chmod a+w UPDATE';
$this->Execute($command);
chdir('update');
$command = 'for i in'.$arg.';do cp --parents $i UPDATE; done && ';
$command .= TAR.' cfz ../update.tar.gz UPDATE';
$this->Execute($command);
chdir('../');
$command = 'rm -rf update;';
$this->Execute($command);
return true;
}
return false;
}
function getRepositoryList()
{
global $dict;
if ( !defined('REP_LIST') || !is_readable(REP_LIST))
{
$this->errors[] = $dict['ERR_CANNOT_READ_REPOSLIST'];
return false;
}
$this->repos_list = file(REP_LIST);
return true;
}
function getRepDirArray($repository)
{
$command = SVNLOOK.sprintf(" tree %s ",$repository);
$result = $this->Execute($command);
if ( !empty($result[ID_ERROUT]) )
{
$this->errors = $result[ID_ERROUT];
return false;
}
$path = array();
$dirArray = array();
$key_old = 0;
foreach ($result[ID_STDOUT] as $line)
{
// if this $line is are not a directory - next line
if (substr(trim($line),-1,1) != '/')
{
continue;
}
else
{
//echo substr($line,-1,1);
}
$key = getIndexFromLine($line);
if ($key > DEPT_TREE )
{
continue;
}
if ($key < $key_old)
{
$path_new = array();
for ($i = 0; $i <= $key; $i++)
{
$path_new[$i] = $path[$i];
}
$path = $path_new;
$key_old = $key;
}
$path[$key] = trim($line);
$url = '';
foreach ($path as $dir)
{
$url .= $dir;
}
$dirArray[] = $url;
}
$this->result = $dirArray;
return true;
}
/**
* Executes an SVN command.
* @param string $cmd Command to execute
* @param string $switch Switches to be applied for the given command
* @param string $arg Arguments of the command
* @return array Result array containing commandline (id = ID_CMDLINE),
* standard out array (id = ID_STDOUT), error array (id = ID_ERROUT),
* and return code of the command (id = ID_CMD_RC).
*/
function Execute($cmd, $arg = '', $switches = '')
{
$descriptorspec = array (
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe to write to
);
$pipes = NULL;
$cmdline = $cmd." ".$switches." ".$arg;
$result = array();
$result[ID_CMDLINE] = $cmdline;
$result[ID_STDOUT] = array();
$result[ID_ERROUT] = array();
$result[ID_CMD_RC] = -1;
$process = proc_open($cmdline, $descriptorspec, $pipes, $cmd);
if (is_resource($process))
{
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
// 1 => readable handle connected to child errout
$result = array();
$result[ID_CMDLINE] = $cmdline;
$result[ID_STDOUT] = $this->GetLineArray($pipes[1]);
$result[ID_ERROUT] = $this->GetLineArray($pipes[2]);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
// It is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
$result[ID_CMD_RC] = proc_close($process);
// echo "CMD: $cmdline<br/>";
// PrintDebugArray($result, "Result");
$this->log_output($result);
}
return $result;
}
/**
* Reads data from a resource (e.g. pipe) and
* returns an array that contains each line for a
* separate index.
* @param resource $handle Resource handle
* @param int $length Maximum line length used if a line is not delimited.
* @return array Array containing a delimited line per index.
*/
function GetLineArray($handle, $length = 4096)
{
$content = array();
$line = fgets($handle, $length);
while ($line !== false)
{
$content[] = $line;
$line = fgets($handle, $length);
}
return $content;
}
/**
* Private function for logging into tmp/log.txt
*
* @param array $response
*/
function log_output($result)
{
global $dict;
$fp = fopen(current_dir().'tmp/log.txt','a');
fputs($fp,'Zeit: '.date('Y-m-d H:i')."\n");
fputs($fp,$dict['COMMAND'].' '.$result[ID_CMDLINE]."\n");
foreach ($result[ID_STDOUT] as $line)
{
fputs($fp,$dict['STD_OUTPUT'].' '.$line);
}
foreach ($result[ID_ERROUT] as $line)
{
fputs($fp,$dict['ERR_OUTPUT'].' '.$line);
}
fputs($fp,"=======================================\n\n");
fclose($fp);
}
}
/**
* Get count of white space from start in $lang
*
* @param string $line
* @return integer $key
*/
function getIndexFromLine($line)
{
$key = 0;
if (preg_match('/^(\s*)/',$line,$matches))
{
$key = strlen($matches[1]);
}
return $key;
}
function current_dir()
{
$path = $_SERVER["SCRIPT_FILENAME"];
$position = strrpos($path,'/') + 1;
return substr($path,0,$position);
}
/**
* Provate foo class for intern use
*
*/
class foo
{
//
}
?>