Skip to content

Commit 0d960d5

Browse files
committed
Require git 1.8.4, and mark the "ffi" driver as experimental
git 1.8.4 is the oldest version the whole suite passes with: before, git simplifies the log of a range filtered by path differently, and git 1.7.1 can't count commits (`rev-list --count` comes with 1.7.2). test-git-versions.php now tests 1.8.4 instead of 1.7.1 and 1.8.3.1. The range test failed with git 1.8.4 too, but because of its setup: git 1.8 adds a line break when it merges a file without one, so the merge differed from both parents. Committed files now end with one. The "ffi" driver isn't covered by the backward compatibility promise: it reimplements git's behavior on top of libgit2, and may still differ from git where its tests don't look.
1 parent 8eca358 commit 0d960d5

8 files changed

Lines changed: 36 additions & 18 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ Changes since [v1.6.0](https://github.com/gitonomy/gitlib/releases/tag/v1.6.0).
99

1010
### Features
1111

12-
- Add an in-process `'ffi'` driver, backed by libgit2 1.9 through PHP's FFI extension, as an
13-
alternative to the default `'cli'` driver: select it with the `'driver' => 'ffi'` option of
12+
- Add an experimental in-process `'ffi'` driver, backed by libgit2 1.9 through PHP's FFI
13+
extension, as an alternative to the default `'cli'` driver: select it with the `'driver' => 'ffi'` option of
1414
`Repository`/`Admin`. It avoids spawning a `git` process for every operation; see
1515
["Choosing a driver"](doc/repository.md#choosing-a-driver) for its requirements, its
1616
differences with the `'cli'` driver, and when it is faster. `benchmark.php` compares both
@@ -77,6 +77,10 @@ Changes since [v1.6.0](https://github.com/gitonomy/gitlib/releases/tag/v1.6.0).
7777

7878
### Minor
7979

80+
- Require git 1.8.4 or later, the oldest version the test suite passes with: it simplifies the
81+
log of a range filtered by path like the current versions, and `Log::count()` needs git
82+
1.7.2. **Breaking:** git 1.7 and 1.8 before 1.8.4 are no longer supported.
83+
([#253](https://github.com/gitonomy/gitlib/pull/253))
8084
- Replace `Gitonomy\Git\Util\StringHelper` with `symfony/string`'s `CodePointString`, which
8185
covers the same UTF-8-aware `strlen`/`substr`/`strpos`/`strrpos` operations.
8286
**Breaking:** `StringHelper` is removed, along with its configurable encoding

‎README.md‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ Gitlib for Gitonomy
33

44
This library provides methods to access Git repository from PHP 8.4+.
55

6-
By default, it runs the `git` binary for every operation: convenient, and it doesn't need anything
7-
built to use. It can instead run [libgit2](https://libgit2.org/) in-process via PHP's `FFI`
8-
extension, which is faster for small reads but slower on long histories: see
6+
By default, it runs the `git` binary (1.8.4 or later) for every operation: convenient, and it
7+
doesn't need anything built to use. It can instead run [libgit2](https://libgit2.org/) in-process
8+
via PHP's `FFI` extension, an experimental driver which is faster for small reads but slower on
9+
long histories: see
910
["Choosing a driver"](doc/repository.md#choosing-a-driver) and
1011
["Performance"](doc/repository.md#performance).
1112

‎UPGRADE-2.0.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@ UPGRADE FROM 1.x to 2.0
22
=======================
33

44
gitlib 2.0 runs every git operation through a driver: `'cli'`, the default,
5-
runs the `git` binary like 1.x did, and `'ffi'` runs libgit2 in-process (see
6-
["Choosing a driver"](doc/repository.md#choosing-a-driver)). Code reading
5+
runs the `git` binary like 1.x did, and the experimental `'ffi'` runs libgit2
6+
in-process (see ["Choosing a driver"](doc/repository.md#choosing-a-driver)). Code reading
77
repositories through `Repository`, `Commit`, `Log`... mostly keeps working:
88
check the points below, starting with errors, dates and classes you extend.
99

1010
Requirements
1111
------------
1212

1313
* PHP 8.4 or later is required.
14+
* git 1.8.4 or later is required by the default `'cli'` driver: before,
15+
git simplifies the log of a range filtered by path differently, and it
16+
can't count commits (`Log::count()`) before 1.7.2.
1417
* `symfony/process` must be `^6.4`, `^7.4` or `^8.1`.
1518
* `symfony/string` `^7.4.6` or `^8.0.6` is a new dependency.
1619

‎composer.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
"symfony/console": "^8.1"
4949
},
5050
"suggest": {
51-
"ext-ffi": "To use the \"ffi\" driver (in-process libgit2, via Repository's 'driver' option) instead of the default \"cli\" driver — also requires libgit2 1.9 to be installed on the system."
51+
"ext-ffi": "To use the experimental \"ffi\" driver (in-process libgit2, via Repository's 'driver' option) instead of the default \"cli\" driver — also requires libgit2 1.9 to be installed on the system."
5252
},
5353
"config": {
5454
"preferred-install": "dist",

‎doc/repository.md‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,21 @@ Options for repository
8585
### Choosing a driver
8686

8787
By default, gitlib spawns a `git` process for every operation (the `'cli'`
88-
driver). You can instead run [libgit2](https://libgit2.org/) in-process,
89-
through PHP's `FFI` extension, by passing the `'ffi'` driver:
88+
driver), which requires git 1.8.4 or later. You can instead run
89+
[libgit2](https://libgit2.org/) in-process, through PHP's `FFI` extension,
90+
by passing the `'ffi'` driver:
9091

9192
```php
9293
$repository = new Repository('/path/to/repo', ['driver' => 'ffi']);
9394
```
9495

96+
> **warning**
97+
>
98+
> The `'ffi'` driver is experimental: it isn't covered by the backward
99+
> compatibility promise, and can change in a minor version. It reproduces
100+
> git's behavior with libgit2, and may still differ from git in cases its
101+
> tests don't cover.
102+
95103
This avoids spawning a process for every operation. The `'ffi'` driver
96104
requires the `ext-ffi` PHP extension and libgit2 1.9: libgit2 changes its
97105
binary interface with every minor version, so any other version is refused.

‎src/Gitonomy/Git/Driver/Ffi/LibGit2DriverFactory.php‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
* Runs libgit2 1.9 in-process, through PHP's FFI extension.
2424
*
2525
* @author Grégoire Pineau <lyrixx@lyrixx.info>
26+
*
27+
* @experimental
2628
*/
2729
final readonly class LibGit2DriverFactory implements DriverFactoryInterface
2830
{

‎test-git-versions.php‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@
2525
const GIT_URL = 'https://github.com/git/git.git';
2626
const BUILDS_PATH = __DIR__.'/git-builds';
2727

28-
// One v1.x and several v2.y releases, picked for how long and how widely each
29-
// shipped as the default git on a major distro, rather than for a spread across
30-
// git's history: v1.7.1 (RHEL/CentOS 6), v1.8.3.1 (RHEL/CentOS 7), v2.17.1 (Ubuntu
31-
// 18.04), v2.25.1 (Ubuntu 20.04), v2.34.1 (Ubuntu 22.04), v2.43.0 (Ubuntu 24.04).
32-
const DEFAULT_VERSIONS = ['v1.7.1', 'v1.8.3.1', 'v2.17.1', 'v2.25.1', 'v2.34.1', 'v2.43.0'];
28+
// v1.8.4, the oldest version gitlib supports, and v2.y releases picked for how
29+
// long and how widely each shipped as the default git on a major distro, rather
30+
// than for a spread across git's history: v2.17.1 (Ubuntu 18.04), v2.25.1 (Ubuntu
31+
// 20.04), v2.34.1 (Ubuntu 22.04), v2.43.0 (Ubuntu 24.04).
32+
const DEFAULT_VERSIONS = ['v1.8.4', 'v2.17.1', 'v2.25.1', 'v2.34.1', 'v2.43.0'];
3333

3434
function sh(array $args, ?string $cwd = null, ?string $logfile = null): Process
3535
{

‎tests/Gitonomy/Git/Tests/LogTest.php‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ public function testFirstMessageEmpty(): void
7878
{
7979
$repository = self::createEmptyRepository();
8080
$tree = self::writeObject($repository, 'tree', '');
81-
// Edge case: first commit lacks a message. Written by hand: git only
82-
// has --allow-empty-message since 1.7.2.
81+
// Edge case: first commit lacks a message.
8382
$commit = self::writeObject($repository, 'commit', "tree {$tree}\nauthor Unit Test <unit_test@unit-test.com> 1000000000 +0000\ncommitter Unit Test <unit_test@unit-test.com> 1000000000 +0000\n\n");
8483
self::git($repository, 'update-ref', ['refs/heads/master', $commit]);
8584

@@ -246,7 +245,8 @@ private static function createRepositoryToCommitTo(): Repository
246245
*/
247246
private static function commit(Repository $repository, string $file, string $content): string
248247
{
249-
file_put_contents($repository->getWorkingDir().'/'.$file, $content);
248+
// Ends with a line break: git 1.8 adds one when it merges a file without.
249+
file_put_contents($repository->getWorkingDir().'/'.$file, $content."\n");
250250
self::git($repository, 'add', [$file]);
251251
self::git($repository, 'commit', ['-m', $content]);
252252

0 commit comments

Comments
 (0)