是否有一个好的支持http的PHPGIT客户端?

是否有一个好的支持http的PHPGIT客户端?,php,git,http,client-library,Php,Git,Http,Client Library,对于我正在从事的一个项目,我们希望使用git作为我们经常修改的某些数据的修订跟踪器。我们在web前端使用php,我们需要一个goo php git客户端来使用。我在互联网上遇到过少数人,他们都有相同的局限性 不支持HTTP。我们需要能够推/拉到远程存储库。我们还需要克隆 理想情况下,我正在寻找一些不使用git命令的东西(即:wrappers to exec()),但如果类运行良好,我愿意解决这个问题。我见过一个C库,它似乎可以实现我想要的功能,但是php语言绑定不完整,http函数被标记为实验性

对于我正在从事的一个项目,我们希望使用git作为我们经常修改的某些数据的修订跟踪器。我们在web前端使用php,我们需要一个goo php git客户端来使用。我在互联网上遇到过少数人,他们都有相同的局限性

不支持HTTP。我们需要能够推/拉到远程存储库。我们还需要克隆

理想情况下,我正在寻找一些不使用git命令的东西(即:wrappers to exec()),但如果类运行良好,我愿意解决这个问题。我见过一个C库,它似乎可以实现我想要的功能,但是php语言绑定不完整,http函数被标记为实验性的

有人对通过php使用git和http有什么见解吗?

这看起来很有希望:(断开的链接;请参阅)

我想这会对你有好处的。以下是对它的描述:

GitPHP是git存储库的web前端。它模拟了标准gitweb的外观,但使用PHP编写,并使用Smarty模板进行定制。它有两个额外功能,包括通过GeSHi PHP类和项目类别支持突出显示语法。它与Windows上的标准git和msysgit一起工作

安装应该相当简单——只需将tarball解压缩到您想要安装它的位置,将config/gitphp.conf.php.example复制到config/gitphp.conf.php,并将conf中的projectroot设置为指向您的裸git存储库所在的目录,并使templates\u c目录可由Web服务器写入(如果尚未写入)。 您可以查看config/gitphp.conf.defaults.php中的所有可用选项和默认值,如果您想覆盖默认值,可以将一个选项复制到配置文件中。如果希望对项目进行更高级的控制,例如定义项目类别或从文本文件加载项目,还可以将config/projects.conf.php.example复制到config/projects.conf.php并对其进行编辑。更详细的说明在附带的自述中

注意:如果您正在升级现有的gitphp.conf.php,则不会被覆盖,但我建议您检查gitphp.conf.defaults.php,以获取可能已添加的新配置选项

您可以查看此网站上运行的实时副本

php是一个围绕Git调用的包装类,它使用
proc\u open
而不是
exec
来运行命令。虽然它没有push/pull方法,但它有一个通用的
run
方法来运行自定义git命令,因此它可以像这样使用:

$repo = Git::open('/path/to/repo');
$repo->run('push origin master');

它也有克隆的方法(
clone\u to
clone\u from
进行本地克隆和
clone\u remote
进行远程克隆)。

一种可能性是使用PHP的SSH库通过连接回web服务器来执行这些操作

或者我找到了一个可以让你通过HTTP克隆和读取其他元数据的方法,但不能推或拉。然而,如果你有足够的勇气去扩展它们,这可能是一个起点。我可以想象,要复制这些流程并使其与各种服务器版本兼容,需要做大量的工作

[收到升级票后于2014年3月23日更新-谢谢!] 我确实找到了一些方法来实现上面的内容(我正在搜索一个实现,画了一个空白,所以我试着写我自己的),这就像我想的那样困难!实际上,我放弃了它,因为我找到了一种更简单的方法,可以在不同的体系结构中实现这一点,但下面是我尝试编写的类。它基本上是有效的,但对我所处的环境变化很脆弱(即,它不能很好地处理错误或问题)

它使用:

  • herzult/php-ssh
  • ssh配置文件—简化代码中身份验证凭据设置的技巧
  • (注意-我不得不快速地从代码中去掉一些细节来发布它。所以你需要花点时间将它集成到你的应用程序/名称空间等中。)


    为什么不直接使用
    exec()
    调用
    git
    来执行所需的命令呢?或者说,
    git
    -wrappers有什么问题?你不需要HTTP支持,因为
    git
    已经有了HTTP支持。您应该将远程存储库克隆到web服务器上的本地存储库,并使用推/拉操作,因为这毕竟是
    git
    的工作方式。我不想调用exec,我正在寻找一个类接口。对exec的调用是草率的,它们不一定是跨平台的,并且引入了潜在的安全漏洞。在一些c库绑定或一些“纯php”代码上运行的类接口比运行shell命令更可取。我确实需要http支持,因为该软件可能在多个Web服务器上运行,在这种情况下,本地存储库是不够的。我不知道为什么这个问题会被解决,因为它非常有用,我还看到了其他几个类似的优化问题,但还没有解决。更新的PHP git客户端包装器也很抱歉,我相信这只是一个存储库浏览器,就像gitweb一样。它不允许您执行任何命令,只允许您浏览文件和历史记录。
    <?php
    /**
     * @author: scipilot
     * @since: 31/12/2013
     */
    
    /**
     * Class GitSSH allows you to perform Git functions over an SSH session.
     * i.e. you are using the command-line Git commands after SSHing to a host which has the Git client.
     *
     * You don't need to know about the SSH to use the class, other than the fact you will need access
     * to a server via SSH which has the Git client installed. Its likely this is the local web server.
     *
     * This was made because PHP has no good native Git client.
     *
     * Requires herzult/php-ssh
     *
     * Example php-ssh config file would be
     *
     * <code>
     *  Host localhost
     *  User git
     *  IdentityFile id_rsa
     *
     *  Host your.host.domain.com
     *  User whoever
     *  IdentityFile ~/.ssh/WhoeverGit
     *</code>
     */
    class GitSSH {
        protected $config;
        protected $session;
        protected $sPath;
        /**
         * @var string
         */
        protected $sConfigPath = '~/.ssh/config';
    
        /**
         * Connects to the specified host, ready for further commands.
         *
         * @param string $sHost         Host (entry in the config file) to connect to.
         * @param string $sConfigPath Optional; config file path. Defaults to ~/.ssh/config,
         *                            which is probably inaccessible for web apps.
         */
        function __construct($sHost, $sConfigPath=null){
            \Log::info('New GitSSH '.$sHost.', '.$sConfigPath);
            if(isset($sConfigPath)) $this->sConfigPath = $sConfigPath;
    
            $this->config = new \Ssh\SshConfigFileConfiguration($this->sConfigPath, $sHost);
            $this->session = new \Ssh\Session($this->config, $this->config->getAuthentication());
        }
    
        public function __destruct() {
            $this->disconnect();
        }
    
        /**
         * Thanks to Steve Kamerman, as there isn't a native disconnect.
         */
        public function disconnect() {
            $this->exec('echo "EXITING" && exit;');
            $this->session = null;
        }
    
        /**
         * Run a command (in the current working directory set by cd)
         * @param $sCommand
         * @return string
         */
        protected function exec($sCommand) {
            //echo "\n".$sCommand."\n";
            $exec = $this->session->getExec();
            $result = $exec->run('cd '.$this->sPath.'; '.$sCommand);
            // todo: parse/scrape the result, return a Result object?
            return $result;
        }
    
        /**
         * CD to a folder. (This not an 'incremental' cd!)
         * Devnote: we don't really execute the cd now, it's appended to other commands. Each command seems to re-login?
         *
         * @param string $sPath Absolute filesystem path, or relative from user home
         */
        public function cd($sPath){
            $this->sPath = $sPath;
    
            // @todo this is useless! each command seems to run in a separate login?
            //$result = $this->exec('cd'); // /; ls');
            //return $result;
        }
    
        /**
         * @return string
         */
        public function ls(){
            $result = $this->exec('ls ');
    
            return $result;
        }
    
        public function gitAdd($sOptions=null, array $aFiles=null){
            $result = $this->exec('git add '
                .(empty($sOptions) ? '' : ' '.$sOptions)
                .(empty($aFiles) ? '' : ' '.implode(' ', $aFiles))
            );
    
            return $result;
        }
    
        public function gitClone($sRepo, $sBranch=null, $sTarget=null){
            \Log::info('GitSSH::clone '.$sRepo.', '.$sBranch.', '.$sTarget);
            $result = $this->exec('git clone '
                .(empty($sBranch) ? '' : ' --branch '.$sBranch)
                .' '.$sRepo
                .' '.$sTarget);
    
            return $result;
        }
    
        public function gitCommit($sMessage, $sOptions=null, array $aFiles=null){
            $result = $this->exec('git commit '
                .'-m "'.addcslashes($sMessage, '"').'"'
                .(empty($sOptions) ? '' : ' '.$sOptions)
                .(empty($aFiles) ? '' : ' '.implode(' ', $aFiles))
            );
    
            return $result;
        }
    
        public function gitPull($sOptions=null, $sRepo=null, $sRefspec=null){
            $result = $this->exec('git pull '
                .(empty($sOptions) ? '' : ' '.$sOptions)
                .(empty($sRepo) ? '' : ' '.$sRepo)
                .(empty($sRefspec) ? '' : ' '.$sRefspec)
            );
    
            return $result;
        }
    
        public function gitPush($sOptions=null, $sRepo=null, $sRefspec=null){
            $result = $this->exec('git push '
                .(empty($sOptions) ? '' : ' '.$sOptions)
                .(empty($sRepo) ? '' : ' '.$sRepo)
                .(empty($sRefspec) ? '' : ' '.$sRefspec)
            );
    
            return $result;
        }
    
        /**
         * @return string the raw result from git status
         */
        public function gitStatus(){
            $result = $this->exec('git status');
            return $result;
        }
    
    }