cu_Cbear 发表于 2012-01-23 02:34

使用PHP操作SVN基础类

本帖最后由 cu_Cbear 于 2012-01-23 02:35 编辑

使用PHP操作SVN基础类






我不想使用PECL包中php svn扩展,一方面对PHP版本有要求,另外一方面对svn代码包有限制,不过最严重的是:对服务器PHP环境的依赖。

一个基础的svn类,应该实现基本的svn操作,如:checkout、update、commit、copy(最常用到)

【目的】

作为一个码农,写出一个被众人使用的组件、类库总是一件令人兴奋的事情,另外,代码的重用性也提倡将某一个方面的操作使用代码封装。

在自动化软件管理中,将代码从svn获取到当前地点,然后再对代码进行部署,并且通过可视化界面对此流程进行管理,这是个不错的想法。另外,通过对svn的管理,实现对代码版本的管理也是一件很有意义的事情。定期去检查代码,然后通知管理员改动信息,都是很好的想法。

【流程】

我想过从svn的协议部分下手,太过复杂,想我几天内是没有办法把它弄完的。因此,通过PHP的shell_exec()下手是个不错的选择。
view plaincopyprint?$result = @shell_exec("svn {$opts}" . $cmd . ' 2> ' . $this->errorfile);
$result = @shell_exec("svn {$opts}" . $cmd . ' 2> ' . $this->errorfile);通过php执行shell,可以有各种空间来进行扩展和使用,但是有如下几点需要注意:

【环境依赖】

依赖Linux环境,

对操作目录、临时目录有操作权限

如果是web环境,同时需要保证apache的执行者具有权限。

【错误处理】

在调用SHELL的时候,倘若svn出错(这是不可避免的),错误不会通过标准输出(STDOUT)输出,而是通过标准错误(STDERR)来输出,标准错误不会被PHP捕捉到,但是会被apache或者操作系统捕捉到,造成PHP执行失败和无法显示的问题。

在这里,我选择了利用shell将错误信息重定向到一个临时文件,然后去读取临时文件来判断执行时是否有错误发生。 view plaincopyprint?       private function shell($cmd){
    $opts = '';
    foreach($this->opts as $key => $item){
      if(!emptyempty($item)){
            $opts .= "--{$key} {$item} ";
      }
    }
    $result = @shell_exec("svn {$opts}" . $cmd . ' 2> ' . $this->errorfile);
    if($this->isResultError()){
      return false;
    }
    return $result;
}
      private function shell($cmd){
                $opts = '';
                foreach($this->opts as $key => $item){
                        if(!empty($item)){
                                $opts .= "--{$key} {$item} ";
                        }
                }
                $result = @shell_exec("svn {$opts}" . $cmd . ' 2> ' . $this->errorfile);
                if($this->isResultError()){
                        return false;
                }
                return $result;
        }【选项】

选项包括:svn的用户名和密码,或者存储svn基本数据的目录(当然前提是有权限读取),可以通过设置来进行 view plaincopyprint?       public function setOptions($options = array()){
    $this->opts = array_merge($this->opts, $options);
}
      public function setOptions($options = array()){
                $this->opts = array_merge($this->opts, $options);
        }【最终】

通过执行测试 和 phpdoc生成文档,即可完成一个基础类的创建

【开闭原则】

也许你知道,也许也不知道,说实话,我对它的理解仅仅局限于字面上。

使每一个与你共事的同事了解开闭原则是一件很重要的事,它能帮助你编写更多可重用的代码类库。

开(对扩展开放)闭(对修改关闭)保证了代码的可重用性和可维护性。




最后,将整个类库贴上。
view plaincopyprint?<?php
/**
* For svn use by php
*
* This class allow you checkout svn files through web
* And allow you update files
* I hope in the later version, it can handle commit and other actions
*
* @example
* <code>
* $phpsvn = new phpsvn();
* $phpsvn->setOptions(array(
*'username' => 'yourname',
*'password' => 'yourpassword'
* ));
* $phpsvn->setPath($svnpath, $localpath);
* $r = $phpsvn->checkout();
* if($r === false){
*echo $phpsvn->error();
* }else{
*print_r($r);
* }
* </code>
* @author hufeng<hufeng@staff.sina.com.cn>
* @version v1.0
* @access sflib
* @package sflib
* @category phpsvn
* @copyright 2012-2013@copyright sflib
*/


class phpsvn
{
    /**
   * svn command options
   *
   * @var array
   */
    private $opts = array(
      'username' => '',
      'password' => '',
      'config-dir' => '',///usr/home/finance/.subversion   
    );
      
    /**
   * error log file
   *
   * Will not save data in this file
   * Just a tmp file store tmp error message
   * @var string
   */
    private $errorfile = '/tmp/phpsvn.err';
      
    /**
   * Error message
   *
   * If no error, error = ''
   * @var string
   */
    private $error = '';
      
    /**
   * The value to return
   *
   * @var array
   */
    private $retValue = array();
      
    /**
   * Svn path
   *
   * @var string
   */
    private $svnpath = '';
      
    /**
   * Local file path where file stored
   *
   * @var string
   */
    private $targetPath = '.';
      
    /**
   * actions tags
   *
   * @var array
   */
    private $shortTags = array('a', 'u', 'd');
      
    /**
   * Set opts of svn command
   *
   * allow opts:
   * username : your svn username
   * password : your svn password
   * config-dir : your execute user config dir
   * @param array $options
   */
    public function setOptions($options = array()){
      $this->opts = array_merge($this->opts, $options);
    }
      
    /**
   * Set svn path & localpath
   *
   * @param string $svnpath svn path
   * @param string $targetpath local path
   * @return void
   */
    public function setPath($svnpath, $targetpath = '.'){
      $this->svnpath = $svnpath;
      $this->targetPath = realpath($targetpath);
    }
      
    /**
   * update from server
   *
   * @return mixed array on success or false on error
   */
    public function update(){
      return $this->doCmd('up');
    }
      
    /**
   * commit file to server
   *
   * @return mixed array on success or false on error
   */
    public function commit(){
      return $this->doCmd('ci');
    }
      
    /**
   * Add file to svn
   *
   * @param string $file filename
   * @return mixed array on success or false on error
   */
    public function add($file){
      return $this->doCmd('add', $file);
    }

    /**
   * Chectout file from svn to local
   *
   * @return mixed array on success or false on error
   */
    public function checkout(){
      return $this->doCmd('co', $this->svnpath);
      //Checked out revision 240772   
    }
      
    /**
   * Execute command for svn
   *
   * support commands:add/checkout(co)/cleanup/commit(ci)/copy(cp)/delete(del,remove,rm)/diff(di)/update (up)
   * todo commands:export
   * help (?, h)
   * import
   * info
   * list (ls)
   * lock
   * log
   * merge
   * mkdir
   * move (mv, rename, ren)
   * propdel (pdel, pd)
   * propedit (pedit, pe)
   * propget (pget, pg)
   * proplist (plist, pl)
   * propset (pset, ps)
   * resolved
   * revert
   * status (stat, st)
   * switch (sw)
   * @param string $cmd
   * @param string $param
   */
    public function doCmd($cmd, $param = ''){
      chdir($this->targetPath);
      $cmd = "{$cmd} {$param}";
      $result = $this->shell($cmd);
      return $this->result($result);
    }
      
    /**
   * Error message last time
   *
   * @return string error message
   */
    public function error(){
      return $this->error;
    }
      
    /**
   * Format the result handle
   *
   * @param string $result result string
   * @return string
   */
    private function result($result){
      if($result === false){
            return false;
      }
      foreach(explode("\n", $result) as $line){
            $line = trim($line);
            $this->retLine($line);
      }
      return $this->retValue;
    }
      
    private function retLine($line){
      $line = strtolower($line);
      if(emptyempty($line)){
            return;
      }
      $retValue = array();
      if(in_array($line, $this->shortTags)){
            $retValue['a'] = $line;
            $retValue['v'] = trim(substr($line, 2));
      }else{
            preg_match('/(+)/', $line, $match);
            $num = intval($match);
            if($num > 0){
                $retValue['a'] = 'v';
                $retValue['v'] = $num;
            }
      }
      $this->retValue[] = $retValue;
    }
      
    /**
   * Get svn file version from result line
   *
   * @param string $line result line
   * @return mixed version number or false if on error
   */
    private function getVersionByLine($line){
      $line = trim(strtolower($line));
      if(preg_match('/(+)/', $line, $match)){
            return $match;
      }
      return false;
    }
    /**
   * Exec shell command
   *
   * @access private
   * @param string $cmd command to be executed
   * @return string result string should been displayed on stdout,
   * @return return false if on error
   */
    private function shell($cmd){
      $opts = '';
      foreach($this->opts as $key => $item){
            if(!emptyempty($item)){
                $opts .= "--{$key} {$item} ";
            }
      }
      $result = @shell_exec("svn {$opts}" . $cmd . ' 2> ' . $this->errorfile);
      if($this->isResultError()){
            return false;
      }
      return $result;
    }
      
    /**
   * Check if on error
   *
   * @param string $result shell result string
   * @return boolen
   */
    private function isResultError(){
      $this->error = file_get_contents($this->errorfile);
      if(emptyempty($this->error)){
            return false;
      }
      return true;
    }
}

?>

健康木乃伊 发表于 2012-01-23 02:35

谢谢分享
页: [1]
查看完整版本: 使用PHP操作SVN基础类