teqneers / php-stream-wrapper-for-git
PHP 的 Git 流包装器
Requires
- php: >=8.0
Requires (Dev)
- knplabs/gaufrette: ~0.11
- phpunit/phpunit: ~9.6
- symfony/yaml: ^3.4|^4.0|^5.0|^6.0
Suggests
- knplabs/gaufrette: to use the Gaufrette adapter
This package is auto-updated.
Last update: 2024-09-24 12:00:10 UTC
README
PHP 的 Git 流包装器 是一个 PHP 库,允许 PHP 代码在应用程序内部与一个或多个 Git 仓库进行交互。该库包含一个 Git 仓库抽象,可用于以编程方式访问 Git 仓库,以及一个可以钩入 PHP 流基础设施的流包装器,允许开发者直接在 Git 仓库中的文件上使用文件和目录访问函数。此外,该库还提供访问 Git 仓库状态信息的方法,例如日志、当前仓库状态或提交信息。
PHP 的 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. });
使用流包装器
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
- 有 Composer 可用于包含依赖项
- 在运行 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 上的测试运行有些不稳定。所有测试都应该显示 绿色,但在清理过程中,可能会出现某些随机访问限制,阻止清理代码删除测试目录。
单元测试套件正在通过 GitHub Actions 在 PHP 8.0、8.1、8.2 和 8.3 上进行持续测试,其当前状态为:
贡献
请随时使用 Git 问题跟踪来报告任何问题或错误。如果您想积极地为库的开发做出贡献,鼓励您克隆仓库并发送 pull requests。
许可
版权 (C) 2023 由 TEQneers GmbH & Co. KG 所有权
特此授予任何人免费获得此软件及其相关文档文件(以下简称“软件”)的副本的权利,允许在不作任何限制的情况下处理该软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件的副本,并允许向获得软件的人提供软件,前提是遵守以下条件
上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。
软件按“原样”提供,不提供任何形式的保证,无论是明示的、暗示的还是与特定目的适用性或非侵权有关的保证。在任何情况下,作者或版权所有者不对任何索赔、损害或其他责任负责,无论这些责任源于合同行为、侵权或其他,无论这些责任是否与软件或其使用或其它操作有关。