php利用内置的svn函数实现的svn版本号的提交、更新、删除、恢复等功能

来源:互联网 发布:抓蚊子 知乎 编辑:程序博客网 时间:2024/05/20 06:23


svnPeer.class.php

<?php/** * php操作svn类,全部利用php内置的svn函数 * * @author wengxianhu * @date 2013-08-05 */class svnPeer{    /* svn用户名 */    public $svn_user = '';    /* svn密码 */    public $svn_password = '';    /* 来源路径 */    public $source_path = '';    /* 目标路径 */    public $dest_path = '';    /* 备份包的路径 */    public $package_path = '';    /**     * 构造函数     *     * @author wengxianhu     * @date 2013-08-05     * @param string $svn_user     * @param string $svn_password     * @param string $source_path     * @param string $dest_path     * @return void     */    public function __construct ($configs = array())    {        if (empty($configs))        {            die('missing parameter');        }        $this->svn_user     = $configs['svn_user'];        $this->svn_password = $configs['svn_password'];        $this->source_path  = $configs['source_path'];        $this->dest_path    = $configs['dest_path'];        $this->package_path    = $configs['package_path'];        $this->_svn_connect();    }    /**     * 配置SVN使用默认的用户名和密码     *     * @author wengxianhu     * @date 2013-08-05     * @return void     */    public function _svn_connect ()    {        svn_auth_set_parameter(SVN_AUTH_PARAM_DEFAULT_USERNAME, $this->svn_user);        svn_auth_set_parameter(SVN_AUTH_PARAM_DEFAULT_PASSWORD, $this->svn_password);    }    /**     * 返回svn版本中的一个文件的内容,默认返回最新的版本号内容     *     * @author wengxianhu     * @date 2013-08-05     * @param string $repos_url     * @param int $revision_no 版本号     * @return string     */    /*    public function _svn_cat ($repos_url, $revision_no = 0)    {        $url = $this->svn_path . '!svn/bc/' . $revision_no . $repos_url;        $ch = curl_init();        curl_setopt($ch, CURLOPT_URL, $url);        curl_setopt($ch, CURLOPT_HTTPGET, 1);        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) ;        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);        curl_setopt($ch, CURLOPT_USERPWD, "$this->svn_user:$this->svn_password");        curl_setopt($ch, CURLOPT_HEADER, 0);        $result=curl_exec($ch);        curl_close($ch);        return $result;    }    */    /**     * 将新增、修改的文件提交到svn中     *     * @author wengxianhu     * @date 2013-08-05     * @param string $msg 版本说明     * @param array $dir_array  目录的绝对路径(目录要一级级往下,不可乱了顺序,如:a、a/a1、b、b/b1、b/b2)     * @param array $file_array  文件的绝对路径     * @param string $package_name  备份包的目录名     * @return array 返回版本号、日期、作者     */    public function _svn_commit ($msg = '', $dir_array = array(), $file_array = array(), $package_name = '')    {        $info = '';        $commit_array = array(); // 将要提交到svn的新目录、新文件、更新文件的路径集合        if (0 < svn_update($this->dest_path)) // 先更新svn        {            if (svn_cleanup($this->dest_path)) // 清理svn            {                $error_array = array();                /* 将新目录加入版本库中 */                $dest_dir = '';                                foreach ($dir_array as $dir_k=>$dir_v)                {                    $dest_dir = $this->dest_path . $dir_v; // 目标目录路径                    if (false === @svn_ls($dest_dir))                    {                        $this->_mkdirm($dest_dir);                        if (false != @svn_add($dest_dir, false))                        {                            array_push($commit_array, $dest_dir);                        }                        else                        {                            array_push($error_array, $dest_dir);                            break;                        }                    }                }                $dest_files = '';                $source_files = '';                $copy_file_array = array(); //覆盖成功的文件集合                foreach ($file_array as $file_k=>$file_v)                {                    $dest_files = $this->dest_path . $file_v; // 目标文件路径                    /* 拷贝文件 */                    $source_files = $this->source_path . $package_name . '/' . $file_v; // 源文件路径                    if (false != $this->_copy_file($source_files, $dest_files))                    {                        array_push($copy_file_array, $dest_files); //用以提交失败后的还原                        if (false === @svn_ls($dest_files))                        {/* 将新文件加入版本库中 */                            if (false != @svn_add($dest_files, false))                            {                                array_push($commit_array, $dest_files);                            }                            else                            {                                array_push($error_array, $dest_files);                                break;                            }                        }                        else                         {                            array_push($commit_array, $dest_files);                        }                    }                    else                    {                        array_push($error_array, $dest_files);                        break;                    }                }                $commit_array = array_unique($commit_array);                /* 将新增、修改的文件和目录提交到svn中 */                $commit_status = false;                if (empty($error_array))                {                    $info = @svn_commit($msg, $commit_array);                    if (false == $info)                    {                    $commit_status = true;                        $info = '提交svn失败';                    }                    elseif ($info[0] == -1)                    {                        $info = '文件包里的文件没做任何修改,不能提交';                    }                }                                /* 提交失败后要把覆盖过去的文件给删除还原 */                if (!empty($error_array) || $commit_status == true)                 {                    if (!empty($copy_file_array))                    {                        $er_num = 0;                        foreach ($copy_file_array as $er_k=>$er_v)                        {                            if (false == @unlink($er_v))                            {                                $er_num++;                                break;                            }                        }                        if ($er_num == 0)                        {                            if (false == @svn_update($this->dest_path))                            {                                $info = '提交svn失败,删除涉及文件后更新失败,请手工更新';                            }                        }                        else                         {                            $info = '提交svn失败,涉及的文件部分删除失败,请手工删除后更新';                        }                    }                }            }        }        return $info;    }    /**     * 删除svn版本库中的文件     *     * @author wengxianhu     * @date 2013-08-05     * @param string $msg 版本说明     * @param array $file_array  元素值是绝对路径的文件     * @return array     */    public function _svn_delete ($msg = '', $file_array = array())    {        $info = '';        $delete_array = array();        $error_array = array();        /* 将删除的文件移除版本库 */        $dest_files = '';        if (svn_cleanup($this->dest_path))        {            foreach ($file_array as $_k=>$_v)            {                $dest_files = $this->dest_path . $_v;                array_push($delete_array, $dest_files);                if (false === @svn_delete($dest_files))                {                    array_pop($delete_array);                }                else                {                    array_push($error_array, $dest_files);                    break;                }            }            /* 将删除的文件提交到svn中 */            if (empty($error_array))            {                $info = @svn_commit($msg, $delete_array);            }        }        return $info;    }    /**     * 提交svn前生成版本号中各个文件最新的文件,当做备份包     *     * @author wengxianhu     * @date 2013-08-05     * @param array $file_array 文件路径名     * @param string $package_name 备份包名     * @return boolean 成功为true,失败为false     */    public function _svn_bak_package ($file_array = array(), $package_name = '')    {        //生成备份包的目录名称为'trunk版本号'        if (!empty($file_array) && !empty($package_name))        {            $files = '';            $source_files = '';            $dest_files = '';            $error_array = array();            foreach ($file_array as $_k=>$_v)            {                $files = preg_replace('/^[^\/]+\/(.*)$/', '$1', $_v);                if (file_exists($this->dest_path . $files))                {                    $source_files = $this->dest_path . $files;                    $dest_files = $this->package_path . $package_name . '/' . $files;                    $revision_no = $this->_get_new_revision_no($source_files); //获取文件最新的版本号                    if (!empty($revision_no))                    {                        $this->_mkdirm(dirname($dest_files));                        $lbv_export = svn_export($source_files, $dest_files, false, $revision_no);                        if (false == $lbv_export)                        {                            array_push($error_array, $files);                            break;                        }                    }                }            }            if (empty($error_array))            {                return true;            }        }        return false;    }    /**     * 恢复指定的svn版本库中的文件     *     * @author wengxianhu     * @date 2013-08-05     * @param string $src 源     * @param string $dst 版本号     * @return array     */    public function _recurse_copy($src, $dst)     {        $dir = opendir($src);        @mkdir($dst);        while(false !== ( $file = readdir($dir)) )         {            if (( $file != '.' ) && ( $file != '..' ))             {                if ( is_dir($src . $file) ) {                    $this->_recurse_copy($src .  $file,$dst . $file);                }                else                 {                    if (false != copy($src . $file,$dst . $file))                    {                        return false;                    }                }            }        }        closedir($dir);        return true;    }    /**     * 恢复指定的svn版本库中的文件     *     * @author wengxianhu     * @date 2013-08-05     * @param int $revision_no 版本号     * @param string $package_name 备份包名     * @return array     */    public function _svn_revert ($revision_no  = '', $package_name = '')    {        $info = '';        if (0 < svn_update($this->dest_path))        {            $log_array = @svn_log($this->dest_path, $revision_no); // 获取指定版本号的相关文件和目录的路径            if (is_array($log_array) && !empty($log_array))            {                $log_array = current($log_array);                $msg = "还原{$revision_no}版本号," . $log_array['msg'];                $files = $log_array['paths'];                $error_array = array();                $commit_array = array();                foreach ($files as $_k=>$_v)                {                    $source_files = '';                    $dest_files = '';                    $dest_files = $this->dest_path . preg_replace('/^\/(.*)/', '$1', $_v['path']);                    /* 只针对文件恢复,不管目录 */                    if (file_exists($dest_files))                    {                        /* 恢复版本号的核心 */                        if ('A' == $_v['action'])                        {/* 删除新增加的文件 */                            if (true == svn_delete($dest_files))                            {                                array_push($commit_array, $dest_files);                            }                            else                            {                                array_push($error_array, $dest_files);                                break;                            }                        }                        else /* 恢复被删除、被更改的文件 */                        {                            $source_files_cp = $this->package_path . $package_name . $_v['path'];                            $dest_files_cp = $dest_files;                            if (false == $this->_copy_file($source_files_cp, $dest_files_cp))                            {                                array_push($error_array, $dest_files_cp);                                break;                            }                            array_push($commit_array, $dest_files_cp);                        }                    }                }                                /* 将修改、删除的文件和目录提交到svn中 */                $commit_status = false;                if (empty($error_array))                {                    $info = @svn_commit($msg, $commit_array);                    if (false == $info)                    {                    $commit_status = true;                        $info = '还原时提交svn失败';                    }                    elseif ($info[0] == -1)                    {                        $info = '文件包里的文件没做任何修改,不能提交';                    }                }                                /* 提交失败后要把覆盖过去的文件给删除还原 */                if (!empty($error_array) || $commit_status == true)                 {                    $er_num = 0; //删除失败次数                    foreach ($error_array as $er_k=>$er_v)                    {                        if (false == @unlink($er_v))                        {                            $er_num++;                            break;                        }                    }                    if ($er_num == 0)                    {                        if (false == @svn_update($this->dest_path))                        {                            $info = '提交svn失败,删除涉及文件后更新失败,请手工更新';                        }                        else                         {                            $info = '还原失败,个别文件svn删除或覆盖出错';                        }                    }                    else                     {                        $info = '提交svn失败,涉及的文件部分删除失败,请手工删除后更新';                    }                }            }            else            {                $info = '该版本号不存在'; //不存在该版本号            }        }        return $info;    }    /**     * 获取版本号的说明     *     * @author wengxianhu     * @date 2013-08-05     * @param string $files svn文件,绝对路径     * @param int $revision_no  svn版本号     * @return string 版本号说明     */    public function _svn_get_msg ($files = '', $revision_no = '')    {        $log_last_info = current(svn_log($files, $revision_no, $revision_no, 1));        $msg = $log_last_info['msg'];        return $msg;    }    /**     * 获取文件最新的版本号     *     * @author wengxianhu     * @date 2013-08-05     * @param string $files svn文件,绝对路径     * @return int 版本号     */    public function _get_new_revision_no ($files = '')    {        $ls_last_info = svn_ls($files);        if (false == $ls_last_info)        {            return '';        }        $ls_last_info = current($ls_last_info);        $revision_no = $ls_last_info['created_rev'];        return $revision_no;    }    /**     * 拷贝文件     *     * @author wengxianhu     * @date 2013-08-05     * @param string $source_files 源文件     * @param string $dest_files 目标文件     * @return bool     */    public function _copy_file ($source_files, $dest_files)    {        if (copy($source_files, $dest_files))        {            return chmod($dest_files, 0644); //文件权限        }        return false;    }    /**     * 创建文件夹     *     * @author wengxianhu     * @date 2013-08-05     * string $path 文件路径(不包括文件名)     * return void     */    public function _mkdirm ($path)    {        if (!file_exists($path))        {            $this->_mkdirm(dirname($path));            mkdir($path, 0755);        }    }        /**     * 获取一个时间段内的svn的版本号信息     *      * @author wengxianhu     * @date 2013-08-15     * @param array $array 数组参数     * @return boolean     */    public function _get_svn_list($array = array())    {        $start_revision = $array['start_revision'];        $end_revision = $array['end_revision'];        if (empty($start_revision)) $start_revision = 0; //起初默认为0        /* 结束默认为最新版本号 */        if (empty($end_revision))        {            $end_revision = svn_update($this->dest_path);            if (false == $end_revision)            {                return false;            }        }        /* 结束版本号大于起初版本号,说明有版本需要同步 */        if ($end_revision > $start_revision)        {            $start_revision = $start_revision + 1;            $svn_list = svn_log($this->dest_path, $start_revision, $end_revision);            if ($svn_list)            {                return $svn_list;            }        }        return false;    }}

zip.class.php

<?php/** * Zip 文件包工具 *  * @author wengxianhu * @date 2013-08-05 */class ZipFolder{    protected $zip;    protected $root;    protected $ignored_names;    public function __construct(){        $this->zip = new ZipArchive;    }    /**     * 解压zip文件到指定文件夹     *     * @access public     * @param string $zipfile 压缩文件路径     * @param string $path    压缩包解压到的目标路径     * @return booleam 解压成功返回 true 否则返回 false    */    public function unzip ($zipfile, $path) {        if ($this->zip->open($zipfile) === true) {            $file_tmp = @fopen($zipfile, "rb");            $bin = fread($file_tmp, 15); //只读15字节 各个不同文件类型,头信息不一样。            fclose($file_tmp);            /* 只针对zip的压缩包进行处理 */            if (true === $this->getTypeList($bin))            {                $result = $this->zip->extractTo($path);                $this->zip->close();                return $result;            }            else            {                return false;            }        }        return false;    }    /**     * 创建压缩文件     *     * @access public     * @param string $zipfile 将要生成的压缩文件路径     * @param strng  $folder  将要被压缩的文件夹路径     * @param array  $ignored 要忽略的文件列表     * @return booleam 压缩包生成成功返回true 否则返回 false    */     public function zip ($zipfile, $folder, $ignored = null) {        $this->ignored_names = is_array($ignored) ? $ignored : $ignored ? array($ignored) : array();        if ($this->zip->open($zipfile, ZIPARCHIVE::CREATE) !== true) {            throw new Exception("cannot open <$zipfile>\n");        }        $folder = substr($folder, -1) == '/' ? substr($folder, 0, strlen($folder)-1) : $folder;        if(strstr($folder, '/')) {            $this->root = substr($folder, 0, strrpos($folder, '/')+1);            $folder = substr($folder, strrpos($folder, '/')+1);        }        $this->createZip($folder);        return $this->zip->close();    }    /**     * 递归添加文件到压缩包     *     * @access private     * @param string $folder 添加到压缩包的文件夹路径     * @param string $parent 添加到压缩包的文件夹上级路径     * @return void    */    private function createZip ($folder, $parent=null) {        $full_path = $this->root . $parent . $folder;        $zip_path = $parent . $folder;        $this->zip->addEmptyDir($zip_path);        $dir = new DirectoryIterator($full_path);        foreach($dir as $file) {            if(!$file->isDot()) {                $filename = $file->getFilename();                if(!in_array($filename, $this->ignored_names)) {                    if($file->isDir()) {                        $this->createZip($filename, $zip_path.'/');                    }else {                        $this->zip->addFile($full_path.'/'.$filename, $zip_path.'/'.$filename);                    }                }            }        }    }    /**     * 读取压缩包文件与目录列表     *     * @access public     * @param string $zipfile 压缩包文件     * @return array 文件与目录列表    */    public function fileList($zipfile) {        $file_dir_list = array();        $file_list = array();        if ($this->zip->open($zipfile) == true) {            for ($i = 0; $i < $this->zip->numFiles; $i++) {                $numfiles = $this->zip->getNameIndex($i);                if (preg_match('/\/$/i', $numfiles))                {                    $file_dir_list[] = $numfiles;                }                else                {                    $file_list[] = $numfiles;                }            }        }        return array('files'=>$file_list, 'dirs'=>$file_dir_list);    }    /**    * 得到文件头与文件类型映射表    *    * @author wengxianhu    * @date 2013-08-10    * @param $bin string 文件的二进制前一段字符    * @return boolean    */    private function getTypeList ($bin)    {        $array = array(            array("504B0304", "zip")        );        foreach ($array as $v)        {            $blen = strlen(pack("H*", $v[0])); //得到文件头标记字节数            $tbin = substr($bin, 0, intval($blen)); ///需要比较文件头长度            if(strtolower($v[0]) == strtolower(array_shift(unpack("H*", $tbin))))            {                return true;            }        }        return false;    }}

filedir.class.php

<?php/** * 文件类 * * @author wengxianhu * @date 2013-08-14 */class filedir{    /* 文件数组 */    public $file_array = array();    /* 目录数组*/    public $folder_array = array();    /* 全部数组 */    public $all_array = array();    /**     * 读取目录下的文件及子目录的路径     *     * @author wengxianhu     * @date 2013-08-05     * @param string $path 文件路径(不包括文件名)     * @param string $file_array 文件数组     * @param string $folder_array 目录数组     * @param string $all_array 全部数组     * return array     */    public function searchFile($path, $file_array, $folder_array, $all_array)    {        if(is_dir($path))        {  //检查文件目录是否存在            $H = @ opendir($path);            while(false !== ($_file=readdir($H)))            {                //检索目录                if(is_dir($path."/".$_file) && !in_array($_file, array(".", "..", "Thumbs.db")))                {                    array_push($this->folder_array, $path."/".$_file);                    array_push($this->all_array, $path."/".$_file);                    $this->searchFile($path."/".$_file, $this->file_array, $this->folder_array, $this->all_array);                //检索文件                }                elseif(file_exists($path."/".$_file) && !in_array($_file, array(".", "..", "Thumbs.db")))                {                    array_push($this->file_array,$path."/".$_file);                    array_push($this->all_array, $path."/".$_file);                }            }            closedir($H);        }        elseif(file_exists($path))        {            array_push($this->file_array, $path);            array_push($this->all_array, $path);        }                return array('dirs'=>$this->folder_array, 'files'=>$this->file_array, 'all'=>$this->all_array);    }        /**     * 循环删除目录和文件函数     *     * @author wengxianhu     * @date 2013-08-15     * @param string $dirName 目录路径     * return array     */    public function delDirAndFile($dirName)    {        if ( $handle = opendir( "$dirName" ) )         {            while ( false !== ( $item = readdir( $handle ) ) )             {               if ( $item != "." && $item != ".." )                {                   if ( is_dir( "$dirName/$item" ) )                    {                        $this->delDirAndFile( "$dirName/$item" );                   }                   else                   {                        unlink( "$dirName/$item" );                   }               }           }           closedir( $handle );           rmdir( $dirName );        }    }}