Skip to content

Commit fdb76f4

Browse files
committed
Document the 2.0 API
Every page of doc/ describes the API of 2.0, its errors, and what differs between the drivers, with examples run against both. The deprecated forms are mentioned once, pointing to UPGRADE-2.0.md, which now lists every change, with a before/after for each deprecation. The CHANGELOG splits breaking changes, features, deprecations and fixes. The README installs 2.0 and shows how to choose the driver.
1 parent b8a745e commit fdb76f4

16 files changed

Lines changed: 1593 additions & 574 deletions

‎CHANGELOG.md‎

Lines changed: 88 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,31 @@ All notable changes to this project are documented in this file.
55
## [Unreleased]
66

77
Changes since [v1.6.0](https://github.com/gitonomy/gitlib/releases/tag/v1.6.0). To upgrade, see
8-
[UPGRADE-2.0.md](UPGRADE-2.0.md).
8+
[UPGRADE-2.0.md](UPGRADE-2.0.md): most of the API of 1.x that 2.0 replaces keeps working,
9+
deprecated until 3.0.
10+
11+
### Breaking changes
12+
13+
- Run every git operation through a driver (`Gitonomy\Git\Driver`): the domain objects call a
14+
`Driver\RepositoryDriverInterface`, typed (hashes, enums, value objects of `Driver\Data`),
15+
instead of building processes and parsing their output. A failing operation always throws, a
16+
missing revision or object a `ReferenceNotFoundException`, a timeout a
17+
`ProcessTimedOutException`; dates are `\DateTimeImmutable`; names in diffs and trees are
18+
UTF-8; references are read again after every write gitlib makes, and peel annotated tags;
19+
the diff of a merge commit is against its first parent; blame lines, tree entries, diff
20+
lines and logs are typed objects; the subject of a message is its first paragraph. See
21+
[UPGRADE-2.0.md](UPGRADE-2.0.md) for every change.
22+
([#253](https://github.com/gitonomy/gitlib/pull/253))
23+
- Require PHP 8.4 or later, Symfony 6.4/7.4/8.1+: most classes are `final` (some `readonly`),
24+
and every method has native types. ([#238](https://github.com/gitonomy/gitlib/pull/238))
25+
- Remove `Gitonomy\Git\Util\StringHelper`, replaced by `symfony/string`, and its configurable
26+
encoding: gitlib reads everything in UTF-8. ([#252](https://github.com/gitonomy/gitlib/pull/252))
27+
- Require git 1.8.4 or later, the oldest version the test suite passes with: it simplifies the
28+
log of a range filtered by path like the current versions, and `Log::count()` needs git
29+
1.7.2. ([#253](https://github.com/gitonomy/gitlib/pull/253))
30+
- `Diff::parse()` throws for a diff without its raw information, deprecated since 1.6.0
31+
([#229](https://github.com/gitonomy/gitlib/pull/229)): parse the output of
32+
`git diff --raw --patch`. ([#253](https://github.com/gitonomy/gitlib/pull/253))
933

1034
### Features
1135

@@ -16,17 +40,27 @@ Changes since [v1.6.0](https://github.com/gitonomy/gitlib/releases/tag/v1.6.0).
1640
differences with `CliDriver`, and when it is faster. `benchmark.php` compares both drivers
1741
on a repository. With php-fpm, `LibGit2Driver::preload()` keeps libgit2 loaded from
1842
`opcache.preload`. ([#253](https://github.com/gitonomy/gitlib/pull/253))
19-
- `Repository` takes the driver running git as its last argument: a
20-
`Driver\Cli\CliDriver` by default, configured through its constructor, or any
21-
`Driver\DriverInterface`, to replace it in tests; see
22-
["Using your own driver"](doc/repository.md#using-your-own-driver). ([#253](https://github.com/gitonomy/gitlib/pull/253))
43+
- `Repository` takes the working directory and the driver as arguments: a `Driver\Cli\CliDriver`
44+
by default, configured through its constructor (git binary, environment, timeout and logger,
45+
which gets every command, clones included), or any `Driver\DriverInterface`, to replace it in
46+
tests; see ["Using your own driver"](doc/repository.md#using-your-own-driver). The driver
47+
finds the repository: linked worktrees, submodules and reftable repositories open, and a
48+
directory that isn't a repository throws right away.
49+
([#253](https://github.com/gitonomy/gitlib/pull/253))
2350
- Add static methods to `Repository` creating repositories, `init()`, `initBare()`,
2451
`cloneFrom()`, `cloneBareFrom()` and `mirrorFrom()`, and checking a repository URL,
2552
`isValidRepository()` and `isValidRepositoryAndBranch()`; see
2653
["Create and access git repositories"](doc/admin.md).
27-
- Add `WorkingCopy::merge()` to support `git merge`: accepts a `Commit`, `Reference` or
28-
string revision, plus optional extra CLI args (e.g. `['--no-ff']`), mirroring the existing
29-
`checkout()` method. ([#248](https://github.com/gitonomy/gitlib/pull/248), fixes #118)
54+
([#253](https://github.com/gitonomy/gitlib/pull/253))
55+
- Add `Repository::getDiff($from, $to)`, `Repository::getMergeBase()` and `WorkingCopy::getDiff()`,
56+
`WorkingCopy::checkoutNewBranch()`, `Branch::moveTo()` and `Branch::isMergedInto()`,
57+
`Log::withOffset()` and `withLimit()`, `Blame::getHunks()` and the line numbers of
58+
`Blame\Line`, `TreeEntry` and `Submodule`, `Diff\DiffLine` and `Diff\DiffLineType`,
59+
`File::isModeChange()`, `FileChange::getAdditions()` and `getDeletions()`,
60+
`PushReference::getFullname()` and `getRange()`, and the SSH and X.509 signatures of tags.
61+
([#253](https://github.com/gitonomy/gitlib/pull/253))
62+
- Add `WorkingCopy::merge()` to support `git merge`, fast-forwarding or not, with a
63+
`FastForward` enum. ([#248](https://github.com/gitonomy/gitlib/pull/248), fixes #118)
3064
- Add `Repository::runProcess()` to expose stderr from successful commands: `run()` only
3165
ever returned stdout, even on success, but some git commands (e.g. `push`) write
3266
meaningful output to stderr even when they succeed. `run()` now delegates to it and keeps
@@ -44,22 +78,52 @@ Changes since [v1.6.0](https://github.com/gitonomy/gitlib/releases/tag/v1.6.0).
4478

4579
### Deprecations
4680

47-
- Deprecate `Admin`, use the static methods of `Repository` instead, and
48-
`Repository::cloneTo()`, use `Repository::cloneFrom()` or `Repository::cloneBareFrom()`
49-
instead; see [UPGRADE-2.0.md](UPGRADE-2.0.md#creating-repositories).
50-
- Deprecate the `command`, `environment_variables`, `inherit_environment_variables` and
51-
`process_timeout` options of `Repository` and `Admin`, pass a `Driver\Cli\CliDriver`
52-
configured through its arguments as the driver of `Repository` instead, and the `debug`
53-
option, as a failing operation always throws; see
54-
[UPGRADE-2.0.md](UPGRADE-2.0.md#configuring-git).
81+
All are removed in 3.0; see [UPGRADE-2.0.md](UPGRADE-2.0.md).
82+
([#253](https://github.com/gitonomy/gitlib/pull/253))
83+
84+
- `Admin`, use the static methods of `Repository`, and `Repository::cloneTo()`.
85+
- The array of options of `Repository` and `Admin` (`working_dir`, `logger`, `command`,
86+
`environment_variables`, `inherit_environment_variables`, `process_timeout`, `debug`): pass
87+
the working directory and a `CliDriver` instead. `Repository::setLogger()` and `getLogger()`.
88+
- Passing `$reload` to `Repository::getReferences()`, `ReferenceBag::update()`,
89+
`Branch::isMergedTo()`, and arguments to `Commit::getIncludingBranches()`.
90+
- Calling `Repository::getDiff()` with one argument, `Log::getDiff()`, `Diff::setRepository()`,
91+
`File::setRepository()`, `addChange()`, `isChangeMode()`, `isDelete()` and `getAnchor()`,
92+
`FileChange::getCount()` and its `LINE_*` constants, reading diff lines as arrays.
93+
- `Log::setOffset()` and `setLimit()`.
94+
- A range of lines as a string in `Repository::getBlame()`, `Blame::getGroupedLines()` and
95+
`Blame\Line::getLine()`.
96+
- `CommitReference`, `Tree::getCommitReferenceEntries()`, reading tree entries as arrays.
97+
- The branch to create of `WorkingCopy::checkout()`, the arguments of `git merge` of
98+
`WorkingCopy::merge()`.
99+
- `Commit::getShortMessage()` and `getFixedShortHash()`, `Repository::shell()`,
100+
`PushReference::getReference()` and `getRevision()`.
55101

56102
### Bug fixes
57103

58-
- Fix `Commit::getDiff()` returning an empty diff for a root commit: it now lists the files the
59-
commit adds. ([#253](https://github.com/gitonomy/gitlib/pull/253))
104+
- Fix `Commit::getDiff()` returning an empty diff for a root commit, and throwing for a merge
105+
commit (`CliDriver`). ([#253](https://github.com/gitonomy/gitlib/pull/253))
60106
- Fix `Repository::getDiff()`, `WorkingCopy::getDiffPending()` and `WorkingCopy::getDiffStaged()`
61-
failing to parse the output of git before 2.16, which writes "..." after abbreviated hashes.
107+
failing to parse the output of git before 2.16, which writes "..." after abbreviated hashes,
108+
and throwing during a conflict. ([#253](https://github.com/gitonomy/gitlib/pull/253))
109+
- Fix the names of files with spaces in diffs, split at the wrong place, the hashes of the files
110+
following a type change, shifted, and hunks of one line, counted as empty.
111+
([#253](https://github.com/gitonomy/gitlib/pull/253))
112+
- Fix annotated tags never resolving to their commit (`ReferenceBag::resolveTags()`,
113+
`Commit::resolveReferences()`), tags created or deleted missing from `getTags()`, and
114+
`getHead()` throwing after a checkout of a new branch: references are read again after
115+
every write gitlib makes. ([#253](https://github.com/gitonomy/gitlib/pull/253))
116+
- Fix `createBranch()` and `createTag()` moving an existing reference instead of refusing it,
117+
a branch named "remotes/x" taken for a remote one, and branches whose name ends with "HEAD"
118+
missing. ([#253](https://github.com/gitonomy/gitlib/pull/253))
119+
- Fix the log of a merge of an unsigned or SSH-signed tag throwing, or swallowing commits up to
120+
the next PGP signature. ([#253](https://github.com/gitonomy/gitlib/pull/253))
121+
- Fix `Commit::getBodyMessage()` losing the second line of a message without an empty line
122+
after its subject, tags without tagger throwing, and SSH-signed tags not seen as signed.
62123
([#253](https://github.com/gitonomy/gitlib/pull/253))
124+
- Fix blame lines numbered from 1 for a range of lines. ([#253](https://github.com/gitonomy/gitlib/pull/253))
125+
- Fix `Hooks` failing silently, in a repository without hooks directory, and writing the hooks
126+
of a linked worktree where git doesn't run them. ([#253](https://github.com/gitonomy/gitlib/pull/253))
63127
- Fix blame lines starting with a TAB character (`Blame\Line::getContent()`): code removing it
64128
must stop doing so. ([#253](https://github.com/gitonomy/gitlib/pull/253))
65129
- Fix reading a commit whose `encoding` header isn't UTF-8, which threw: its message, author and
@@ -82,9 +146,9 @@ Changes since [v1.6.0](https://github.com/gitonomy/gitlib/releases/tag/v1.6.0).
82146
branch existed.
83147
- `Tag::getBodyMessage()` dropped or truncated a line for annotated tags using the
84148
standard `subject\n\nbody` convention.
85-
- `Repository::run()` can return `null` on failure when `debug=false`; several call sites
86-
(`Tag::isAnnotated()`, `PushReference::isForce()`, `Blob::getContent()`, ...) did not
87-
handle that case and produced wrong data or crashed. All call sites now check for `null`.
149+
- With the `debug` option set to `false`, several call sites (`Tag::isAnnotated()`,
150+
`PushReference::isForce()`, `Blob::getContent()`, ...) produced wrong data or crashed
151+
when git failed.
88152
- `Repository::shell()` interpolated the repository path into the shell command without
89153
escaping it; it is now passed through `escapeshellarg()`.
90154
- `Hooks::set()` created hook scripts world-writable (`0777`); they are now created
@@ -93,50 +157,9 @@ Changes since [v1.6.0](https://github.com/gitonomy/gitlib/releases/tag/v1.6.0).
93157

94158
### Minor
95159

96-
- Parse only diffs with their raw information, the output of `git diff --raw --patch`.
97-
**Breaking:** `Diff::parse()` throws an `InvalidArgumentException` for a diff without it,
98-
deprecated since 1.6.0 ([#229](https://github.com/gitonomy/gitlib/pull/229)).
99-
([#253](https://github.com/gitonomy/gitlib/pull/253))
100-
- Require git 1.8.4 or later, the oldest version the test suite passes with: it simplifies the
101-
log of a range filtered by path like the current versions, and `Log::count()` needs git
102-
1.7.2. **Breaking:** git 1.7 and 1.8 before 1.8.4 are no longer supported.
103-
([#253](https://github.com/gitonomy/gitlib/pull/253))
104-
- Replace `Gitonomy\Git\Util\StringHelper` with `symfony/string`'s `CodePointString`, which
105-
covers the same UTF-8-aware `strlen`/`substr`/`strpos`/`strrpos` operations.
106-
**Breaking:** `StringHelper` is removed, along with its configurable encoding
107-
(`getEncoding()`/`setEncoding()`); the library now consistently targets `UTF-8`.
108-
([#252](https://github.com/gitonomy/gitlib/pull/252))
109-
- Introduce a driver abstraction (`Gitonomy\Git\Driver`) between the domain objects and git:
110-
every operation goes through a `Driver\DriverInterface` returning value objects
111-
(`Driver\Data\CommitData`, `TreeEntryData`, `ReferenceData`, `TagData`, `BlameLineData`),
112-
instead of building processes and parsing their output across the domain classes.
113-
`CliDriver`, the default, keeps running the `git` binary.
114-
**Breaking** (see [UPGRADE-2.0.md](UPGRADE-2.0.md) for the complete list):
115-
- `Repository` throws on unknown options.
116-
- The `debug` option set to `false` is not supported anymore: a failing operation always
117-
throws, an `Exception\DriverException` (`ProcessException` with `CliDriver`) or a more
118-
specific exception, and never returns empty data. `Repository::run()` returns a `string`, and
119-
`Repository::getHead()` and `Repository::getHeadCommit()` never return `null`.
120-
`Commit::getIncludingBranches()`, `Tag::isAnnotated()` and `ReferenceBag` throw where they
121-
returned `false` or an empty result. Failures are no longer logged at the `error` level.
122-
- `Commit::getAuthorDate()`, `Commit::getCommitterDate()` and `Tag::getTaggerDate()` return a
123-
`\DateTimeImmutable`.
124-
- File names in diffs and trees are returned in UTF-8, instead of git's quoted form (which
125-
depended on `core.quotePath` for non-ASCII names in diffs).
126-
- `Commit::setData()` and `Commit`'s constructor third argument take a
127-
`Driver\Data\CommitData`. The parsers of `Gitonomy\Git\Parser` other than `DiffParser`
128-
and `ParserBase` moved to `Driver\Cli\Parser`, and `CommitParser` is merged into
129-
`LogParser`.
130-
- `PushReference::isForce()` returns `true` for histories without a common ancestor, where
131-
the constructor threw.
132-
160+
- CI tests git 1.8.4 and 2.25.1, analyses the tests and the libgit2 driver with PHPStan,
161+
checks the archive Composer installs, and the suite deletes what it creates, in any order.
133162
([#253](https://github.com/gitonomy/gitlib/pull/253))
134-
- Modernize for PHP 8.4+, Symfony 6.4/7.4/8.1+ and PHPUnit 12: full property/parameter/return
135-
type coverage, `readonly`/`final` where applicable, PHPUnit 12 attributes, and new
136-
php-cs-fixer/PHPStan/Castor tooling.
137-
**Breaking:** the minimum supported PHP version is now 8.4, most classes are `final` (some
138-
`readonly`), and every method has native types: see [UPGRADE-2.0.md](UPGRADE-2.0.md).
139-
([#238](https://github.com/gitonomy/gitlib/pull/238))
140163
- Add a regression test for reading a blob's content in a tree that also contains a
141164
submodule. ([#243](https://github.com/gitonomy/gitlib/pull/243))
142165
- Replace the network-dependent test fixture (cloned from GitHub on every run) with a local,

‎README.md‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ or edit your `composer.json` file by hand:
2424
```json
2525
{
2626
"require": {
27-
"gitonomy/gitlib": "^1.3"
27+
"gitonomy/gitlib": "^2.0"
2828
}
2929
}
3030
```
3131

32+
Upgrading from 1.x? Read [UPGRADE-2.0.md](UPGRADE-2.0.md).
33+
3234
Example Usage
3335
-------------
3436

@@ -43,9 +45,23 @@ foreach ($repository->getReferences()->getBranches() as $branch) {
4345
echo '- '.$branch->getName().PHP_EOL;
4446
}
4547

48+
echo $repository->getHeadCommit()->getSubjectMessage().PHP_EOL;
49+
50+
// Any git command, with the default driver only
4651
$repository->run('fetch', ['--all']);
4752
```
4853

54+
The last argument of `Repository` is the driver running git. It is `CliDriver`, which runs the
55+
`git` binary, by default. To run libgit2 instead, pass a `LibGit2Driver`: everything above works
56+
the same, except `run()`, which needs the `git` binary.
57+
58+
```php
59+
use Gitonomy\Git\Driver\Ffi\LibGit2Driver;
60+
use Gitonomy\Git\Repository;
61+
62+
$repository = new Repository('/path/to/repository', driver: new LibGit2Driver());
63+
```
64+
4965
API Documentation
5066
-----------------
5167

@@ -58,7 +74,7 @@ API Documentation
5874
+ [Hooks](doc/hooks.md)
5975
+ [Log](doc/log.md)
6076
+ [References](doc/references.md)
61-
+ [Repository](doc/repository.md)
77+
+ [Repository](doc/repository.md): opening a repository, drivers, errors
6278
+ [Revision](doc/revision.md)
6379
+ [Tree](doc/tree.md)
6480
+ [Working Copy](doc/workingcopy.md)

0 commit comments

Comments
 (0)