@@ -5,7 +5,31 @@ All notable changes to this project are documented in this file.
55## [ Unreleased]
66
77Changes 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,
0 commit comments