PHP的GIT流包装器
PHP的GIT流包装器是PHP库,允许PHP代码与应用程序内部的一个或多个GIT存储库进行交互。该库由GIT存储库抽象组成,该抽象可用于编程访问GIT存储库和流包装器,该流程包装器可以挂载到PHP流基础架构中,以允许开发人员在GIT存储库中的文件上直接使用文件和目录访问功能。该库提供了访问GIT存储库的状态信息的方法,例如日志,当前存储库状态或提交信息。
PHP Core的GIT流包装器是围绕GIT命令行二进制的包装器,因此需要在运行PHP代码的机器上安装GIT。 PHP的GIT流包装器不包括GIT协议抽象,它依赖于Git命令行二进制的所有功能。
该代码当前正在运行稳定(请参阅下面的Windows上的注释),应为API稳定。但是,它不是完整的 – 因此,请随时请求您需要的功能。
例子
使用存储库抽象
use TQ \\ Git \\ Repository \\ Repository ; // open an already initialized repository $ git = Repository:: open ( \' /path/to/your/repository \' , \' /usr/bin/git \' ); // open repository and create path and init repository if necessary $ git = Repository:: open ( \' /path/to/your/repository \' , \' /usr/bin/git \' , 0755 ); // get current branch $ branch = $ git -> getCurrentBranch (); // get status of working directory $ status = $ git -> getStatus (); // are there uncommitted changes in the staging area or in the working directory $ isDirty = $ git -> isDirty (); // retrieve the commit log limited to $limit entries skipping the first $skip $ log = $ git -> getLog ( $ limit , $ skip ); // retrieve the second to last commit $ commit = $ git -> showCommit ( \' HEAD^ \' ); // list the directory contents two commits before $ list = $ git -> listDirectory ( \' . \' , \' HEAD^^ \' ); // show contents of file $file at commit abcd123... $ contents = $ git -> showFile ( $ file , \' abcd123 \' ); // write a file and commit the changes $ commit = $ git -> writeFile ( \' test.txt \' , \' Test \' , \' Added test.txt \' ); // remove multiple files $ commit = $ git -> removeFile ( \' file_* \' , \' Removed all files not needed any more \' ); // rename a file $ commit = $ c -> renameFile ( \' test.txt \' , \' test.txt-old \' , \' Made a backup copy \' ); // do some file operations and commit all changes at once $ result = $ git -> transactional ( function ( TQ \\ Vcs \\ Repository \\ Transaction $ t ) { file_put_contents ( $ t -> getRepositoryPath (). \' /text1.txt \' , \' Test 1 \' ); file_put_contents ( $ t -> getRepositoryPath (). \' /text2.txt \' , \' Test 2 \' ); unlink ( $ t -> resolvePath ( \' old.txt \' )); rename ( $ t -> resolvePath ( \' to_keep.txt \' ), $ t -> resolvePath ( \' test3.txt \' )); $ t -> setCommitMsg ( \' Don \\\' t know what to write here \' ); // if we throw an exception from within the callback the changes are discarded // throw new Exception(\'No we don\\\'t want to make these changes\'); // note: the exception will be re-thrown by the repository so you have to catch // the exception yourself outside the transactional scope. });
使用StreamWrapper
use TQ \\ Git \\ StreamWrapper \\ StreamWrapper ; // register the wrapper StreamWrapper:: register ( \' git \' , \' /usr/bin/git \' ); // read the contents of a file $ content = file_get_contents ( \' git:///path/to/your/repository/file_0.txt \' ); // show contents of a file at commit abcd123... $ content = file_get_contents ( \' git:///path/to/your/repository/file_0.txt#abcd123 \' ); // show contents of a file two commits before $ content = file_get_contents ( \' git:///path/to/your/repository/file_0.txt#HEAD^^ \' ); // show the directory information two commits before $ directory = file_get_contents ( \' git:///path/to/your/repository/#HEAD^^ \' ); // list directory contents two commits before $ dir = opendir ( \' git:///path/to/your/repository/subdir#HEAD^^ \' ); while ( $ f = readdir ( $ dir )) { echo $ f . PHP_EOL ; } closedir ( $ dir ); // recursively traverse the repository two commits before $ dir = new RecursiveDirectoryIterator ( \' git:///path/to/your/repository#HEAD^^ \' ); $ it = new RecursiveIteratorIterator ( $ dir , RecursiveIteratorIterator:: SELF_FIRST ); foreach ( $ it as $ fileInfo ) { echo str_repeat ( \' \' , $ it -> getDepth () * 3 ). $ fileInfo -> getFilename (). PHP_EOL ; } // retrieve the second to last commit $ commit = file_get_contents ( \' git:///path/to/your/repository?commit&ref=HEAD^^ \' ); // retrieve the commit log limited to 5entries skipping the first 2 $ log = file_get_contents ( \' git:///path/to/your/repository?log&limit=5&skip=2 \' ); // remove a file - change is committed to the repository unlink ( \' git:///path/to/your/repository/file_to_delete.txt \' ); // rename a file - change is committed to the repository rename ( \' git:///path/to/your/repository/old.txt \' , \' git:///path/to/your/repository/new.txt \' ); // remove a directory - change is committed to the repository rmdir ( \' git:///path/to/your/repository/directory_to_delete \' ); // create a directory - change is committed to the repository // this creates a .gitkeep file in new_directory because Git does not track directories mkdir ( \' git:///path/to/your/repository/new_directory \' ); // write to a file - change is committed to the repository when file is closed $ file = fopen ( \' git:///path/to/your/repository/test.txt \' , \' w \' ); fwrite ( $ file , \' Test \' ); fclose ( $ file ); // support for stream context $ context = stream_context_create ( array ( \' git \' => array ( \' commitMsg \' => \' Hello World \' , \' author \' => \' Luke Skywalker <skywalker@deathstar.com> \' ) )); $ file = fopen ( \' git:///path/to/your/repository/test.txt \' , \' w \' , false , $ context ); fwrite ( $ file , \' Test \' ); fclose ( $ file ); // file gets committed with the preset commit message and author // append to a file using file_put_contents using a custom author and commit message $ context = stream_context_create ( array ( \' git \' => array ( \' commitMsg \' => \' Hello World \' , \' author \' => \' Luke Skywalker <skywalker@deathstar.com> \' ) )); file_put_contents ( \' git:///path/to/your/repository/test.txt \' , \' Test \' , FILE_APPEND , $ context ); // it is now possible to register repository-specific paths on the stream wrapper StreamWrapper:: getRepositoryRegistry ()-> addRepositories ( array ( \' repo1 \' => Repository:: open ( \' /path/to/repository/1 \' , \' /usr/bin/git \' , false ), \' repo2 \' => Repository:: open ( \' /path/to/repository/2 \' , \' /usr/bin/git \' , false ), ) ); $ content1 = file_get_contents ( \' git://repo1/file_0.txt \' ); $ content2 = file_get_contents ( \' git://repo2/file_0.txt \' ); // unregister the wrapper if needed StreamWrapper:: unregister ();
要求
- PHP> = 8.0.0
- 作曲家可包括依赖项
- 在运行PHP代码的机器上安装了GIT
- 如果要使用SVN组件,则在运行PHP代码的机器上安装了SVN
运行测试
- 克隆存储库
- 运行
composer install以安装依赖项并创建自动加载器 - 复制
phpunit.xml.dist到phpunit.xml - 将
phpunit.xml中的GIT_BINARY,SVN_BINARY和SVN_ADMIN_BINARY常数调整到git二进制的路径 - 从克隆的项目文件夹中运行
phpunit
请注意,该库已在Mac OS X 12.6上进行了测试,其中包含捆绑的PHP 8.0.27、8.1.14和8.2.1(GIT版本2.39.1)和几个Ubuntu Linux安装。由于目前未知原因,该测试在Windows上运行有些不稳定。所有测试均应为绿色,但是在清理过程中,可能会有一些访问限制随机启动并防止清理代码删除测试目录。
单位测试套件在PHP 8.0、8.1、8.2和8.3上的GITHUB操作不断测试,其当前状态为:
贡献
请随时使用GIT问题跟踪来报告任何问题或错误。如果您想积极地开发图书馆,则鼓励您克隆存储库并发送拉动请求。
执照
Teqneers GmbH&Co。KG版权(C)2023
特此免费获得许可,免费授予任何获得此软件副本和相关文档文件(“软件”)的人,以无限制地处理软件,包括无限制的使用权,复制,复制,修改,合并,发布,分发,分发,分发,分配,sublicense和/或允许软件允许与以下条件相关的软件,以下是以下条件。
上述版权通知和此许可通知应包含在软件的所有副本或大量部分中。
该软件是“原样”提供的,没有任何形式的明示或暗示保证,包括但不限于适销性,特定目的的适用性和非侵权的保证。在任何情况下,作者或版权持有人都不应对任何索赔,损害赔偿或其他责任责任,无论是在合同,侵权的诉讼中还是其他责任,是由软件,使用或与软件中的使用或其他交易有关的。
