From 8743ffb59e40c68302345580dc0b50dcc37e68dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Thu, 15 Oct 2026 15:52:22 +0200 Subject: [PATCH] Smooth the upgrade from 1.7 1.7 has the API of 2.0 that can be added without breaking 1.x, and deprecates what 2.0 replaces: 2.0 introduces no deprecation of its own, they are all deprecated since 1.7. So the lines of a hunk and the entries of a tree get the methods 1.7 has: FileChange::getDiffLines(), iterating a Tree, Tree::getBlobs(), getTrees() and getSubmodules(). The methods returning arrays are deprecated, and keep returning the arrays of 1.x until 3.0, instead of objects readable as arrays. UnexpectedValueException, which 2.0 no longer throws, has nothing to replace it in 1.7: it isn't deprecated. UPGRADE-2.0.md explains how to support 1.x and 2.x with a single code path, and the branch alias lets "^2.0@dev" install main. --- CHANGELOG.md | 24 ++- UPGRADE-2.0.md | 171 ++++++++++++++++-- composer.json | 5 + doc/admin.md | 2 +- doc/blame.md | 6 +- doc/branch.md | 4 +- doc/commit.md | 6 +- doc/diff.md | 22 ++- doc/log.md | 2 +- doc/references.md | 4 +- doc/repository.md | 10 +- doc/tree.md | 29 +-- doc/workingcopy.md | 4 +- src/Gitonomy/Git/Admin.php | 30 +-- src/Gitonomy/Git/Blame.php | 4 +- src/Gitonomy/Git/Blame/Line.php | 4 +- src/Gitonomy/Git/Commit.php | 10 +- src/Gitonomy/Git/CommitReference.php | 4 +- src/Gitonomy/Git/Diff/Diff.php | 4 +- src/Gitonomy/Git/Diff/DiffLine.php | 39 +--- src/Gitonomy/Git/Diff/File.php | 20 +- src/Gitonomy/Git/Diff/FileChange.php | 56 ++++-- .../Exception/UnexpectedValueException.php | 3 +- src/Gitonomy/Git/Log.php | 12 +- src/Gitonomy/Git/PushReference.php | 16 +- src/Gitonomy/Git/Reference/Branch.php | 4 +- src/Gitonomy/Git/ReferenceBag.php | 4 +- src/Gitonomy/Git/Repository.php | 28 +-- src/Gitonomy/Git/Tree.php | 129 +++++++++---- src/Gitonomy/Git/TreeEntry.php | 38 +--- src/Gitonomy/Git/WorkingCopy.php | 2 +- tests/Gitonomy/Git/Tests/AdminTest.php | 24 +-- tests/Gitonomy/Git/Tests/BlameTest.php | 2 +- tests/Gitonomy/Git/Tests/BlobTest.php | 2 +- tests/Gitonomy/Git/Tests/CommitTest.php | 6 +- tests/Gitonomy/Git/Tests/DiffTest.php | 58 ++++-- tests/Gitonomy/Git/Tests/LogTest.php | 6 +- .../Gitonomy/Git/Tests/PushReferenceTest.php | 8 +- tests/Gitonomy/Git/Tests/ReferenceTest.php | 18 +- tests/Gitonomy/Git/Tests/RepositoryTest.php | 12 +- tests/Gitonomy/Git/Tests/TreeTest.php | 79 ++++++-- tests/Gitonomy/Git/Tests/WorkingCopyTest.php | 2 +- 42 files changed, 582 insertions(+), 331 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51456c44..8d6c9876 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,8 +16,8 @@ deprecated until 3.0. missing revision or object a `ReferenceNotFoundException`, a timeout a `ProcessTimedOutException`; dates are `\DateTimeImmutable`; names in diffs and trees are UTF-8; references are read again after every write gitlib makes, and peel annotated tags; - the diff of a merge commit is against its first parent; blame lines, tree entries, diff - lines and logs are typed objects; the subject of a message is its first paragraph. See + the diff of a merge commit is against its first parent; blame lines and logs are typed + objects; the subject of a message is its first paragraph. See [UPGRADE-2.0.md](UPGRADE-2.0.md) for every change. ([#253](https://github.com/gitonomy/gitlib/pull/253)) - Return the dates of commits and tags at the UTC offset of their author, committer or tagger, @@ -43,6 +43,9 @@ deprecated until 3.0. `The git command "clone" failed (exit 128): fatal: ...`. The command line, the rest of the error output and the output are no longer in the message: `getErrorOutput()` and `getOutput()` return the outputs of git. ([#254](https://github.com/gitonomy/gitlib/pull/254)) +- `Tree::resolvePath()` throws an `InvalidArgumentException` for a path through a submodule, + instead of an `Exception\UnexpectedValueException`, which gitlib no longer throws. + ([#254](https://github.com/gitonomy/gitlib/pull/254)) - When git can't start, a missing binary for instance, `CliDriver` throws a `DriverException` instead of a `ProcessException`, with a message of one line, without the command line: `The git command "clone" could not start: ...`. @@ -78,7 +81,9 @@ deprecated until 3.0. `Repository::getSizeInBytes()` and `WorkingCopy::getDiff()`, `WorkingCopy::checkoutNewBranch()`, `Branch::moveTo()` and `Branch::isMergedInto()`, `Log::withOffset()` and `withLimit()`, `Blame::getHunks()` and the line numbers of - `Blame\Line`, `TreeEntry` and `Submodule`, `Diff\DiffLine` and `Diff\DiffLineType`, + `Blame\Line`, `FileChange::getDiffLines()`, which returns `Diff\DiffLine` objects typed by + `Diff\DiffLineType`, iterating a `Tree`, which gives `TreeEntry` objects, + `Tree::getBlobs()`, `getTrees()` and `getSubmodules()`, `Submodule`, `File::isModeChange()`, `FileChange::getAdditions()` and `getDeletions()`, `PushReference::getFullname()`, `getRange()`, `isCreation()` and `isDeletion()`, and the SSH and X.509 signatures of tags. ([#253](https://github.com/gitonomy/gitlib/pull/253), @@ -103,7 +108,8 @@ deprecated until 3.0. ### Deprecations All are removed in 3.0; see [UPGRADE-2.0.md](UPGRADE-2.0.md). -([#253](https://github.com/gitonomy/gitlib/pull/253)) +([#253](https://github.com/gitonomy/gitlib/pull/253)) 1.7 deprecates them already: they are +all deprecated since 1.7. - `Admin`, replaced by the static methods of `Repository`, and `Repository::cloneTo()`, replaced by `cloneFrom()` and `cloneBareFrom()`. @@ -116,18 +122,20 @@ All are removed in 3.0; see [UPGRADE-2.0.md](UPGRADE-2.0.md). replaced by `Branch::moveTo()` and `isMergedInto()`. - Calling `Repository::getDiff()` with one argument, `Log::getDiff()`, `Diff::setRepository()`, `File::setRepository()`, `addChange()`, `isChangeMode()`, `isDelete()` and `getAnchor()`, - `FileChange::getCount()` and its `LINE_*` constants, reading diff lines as arrays. + `FileChange::getCount()`, `getLines()`, replaced by `getDiffLines()`, and the `LINE_*` + constants, replaced by `DiffLineType`, lines passed to the constructor of `FileChange` as + arrays. - `Log::setOffset()` and `setLimit()`. - A range of lines as a string in `Repository::getBlame()`, `Blame::getGroupedLines()` and `Blame\Line::getLine()`. -- `CommitReference`, `Tree::getCommitReferenceEntries()`, reading tree entries as arrays. +- `CommitReference`, `Tree::getCommitReferenceEntries()`, `getEntries()`, `getBlobEntries()` + and `getTreeEntries()`: iterate the tree, or use `getBlobs()`, `getTrees()` and + `getSubmodules()`. - The branch to create of `WorkingCopy::checkout()`. - `Commit::getShortMessage()` and `getFixedShortHash()`, `Repository::shell()`, `PushReference::getReference()`, `getRevision()`, `isCreate()` and `isDelete()`. - `Repository::getSize()`, in kilobytes: use `getSizeInBytes()`. ([#254](https://github.com/gitonomy/gitlib/pull/254)) -- `Exception\UnexpectedValueException`, which gitlib no longer throws. - ([#254](https://github.com/gitonomy/gitlib/pull/254)) ### Security diff --git a/UPGRADE-2.0.md b/UPGRADE-2.0.md index 312308f5..8b3b3e0b 100644 --- a/UPGRADE-2.0.md +++ b/UPGRADE-2.0.md @@ -12,6 +12,10 @@ call triggers a deprecation (`E_USER_DEPRECATED`, through them. Log the deprecations of your application to find them. The other changes, listed below too, break code that relies on them. +Upgrade to 1.7 first, which requires PHP 8.1: it has most of the +replacements, and triggers the deprecations of the API they replace (see +[Supporting 1.x and 2.x](#supporting-1x-and-2x)). + Requirements ------------ @@ -28,6 +32,65 @@ Requirements * Repositories using SHA-256 hashes are refused, with an `UnsupportedOperationException`, by both drivers. +Supporting 1.x and 2.x +---------------------- + +gitlib 1.7 has the API of 2.0 that can be added without breaking 1.x, and +deprecates what 2.0 replaces or breaks: `new Repository($dir, $workingDir, +$driver)` with a `CliDriver` of the same arguments, the static methods of +`Repository` creating repositories, `Diff::parse($rawDiff, $repository)`, +`Repository::getDiff($from, $to)`, `FileChange::getDiffLines()`, iterating +a `Tree`, `Log::withLimit()`, `Branch::isMergedInto()`, +`Blame::getHunks()`... Fix the deprecations of 1.7, then require +`^1.7 || ^2.0`: a library supporting PHP 8.1 to 8.3 gets 1.7 there, and 2.0 +from PHP 8.4, with the same code. + +Before: + +```php +$repository = new Repository($gitDir, ['working_dir' => $workingDir, 'logger' => $logger]); +$diff = Diff::parse($rawDiff); +$diff->setRepository($repository); +``` + +After, with 1.7 and 2.0: + +```php +use Gitonomy\Git\Driver\Cli\CliDriver; + +$repository = new Repository($gitDir, $workingDir, new CliDriver(logger: $logger)); +$diff = Diff::parse($rawDiff, $repository); +``` + +1.7 breaks nothing of 1.x, so: + +* Pass by position the arguments whose name changes in 2.0 (see + [Extending gitlib](#extending-gitlib)): 1.7 keeps the names of 1.x. So + do the arguments 1.7 adds to `Repository::getDiff()`, `getBlame()`, + `Diff::parse()`, `Diff::fromArray()` and `File::fromArray()`: their + signature leaves them out, not to break the classes overriding these + methods. +* `ReferenceBag::createBranch()` and `createTag()` keep a revision name as + the hash of the reference they return, like 1.x: pass a `Revision` to + get the hash of its commit with both versions. +* The submodules of trees are `CommitReference` objects, which extend + `Submodule` in 1.7: check them with `instanceof Submodule`. +* `File::toArray()` has no `is_copy` key in 1.7. + +What 1.7 can't bring, as it would break 1.x, behaves differently with +both versions: + +* With a range of lines, `Blame::getLines()` and `getLine()` number the + lines from 1 in 1.7, like the file in 2.0: use `Line::getNumber()`, or + `Blame::getHunks()`, numbered like the file in 1.7 too. +* 1.7 doesn't read the references again after a write: open a new + `Repository` to read them, with both versions. `getReferences(true)` is + deprecated in 1.7 too. +* The classes `final` in 2.0 are only `@final` in 1.7: see + [Testing code using gitlib](#testing-code-using-gitlib). +* The other changes listed below: dates, the stricter parser of diffs, + the directory git runs in, the exceptions... + Opening a repository -------------------- @@ -43,6 +106,16 @@ Opening a repository request. Pass the variables git needs to the `environmentVariables` argument instead. + git inherits `$_ENV`, and the variables of `getenv()` that `$_SERVER` + holds too, like Symfony Process passes them: a variable an application + only writes in `$_SERVER`, without `putenv()` nor `$_ENV`, which the + option passed, no longer reaches git. A command line application + relying on it passes `$_SERVER` itself: + + ```php + $driver = new CliDriver(environmentVariables: array_filter($_SERVER, is_string(...))); + ``` + Before: ```php @@ -233,11 +306,13 @@ Diffs changes when constructed: `Diff::setRepository()`, `File::setRepository()` and `File::addChange()` are deprecated. `Diff::parse()` and `fromArray()` take the repository to read blobs from. -* The lines of a hunk, `FileChange::getLines()`, are `Diff\DiffLine` - objects, with `getType()`, a `Diff\DiffLineType`, and `getContent()`: - reading them as arrays is deprecated, as the `FileChange::LINE_*` - constants and `FileChange::getCount()`, replaced by `getAdditions()` and - `getDeletions()`. +* `FileChange::getDiffLines()` returns the lines of a hunk as + `Diff\DiffLine` objects, with `getType()`, a `Diff\DiffLineType`, and + `getContent()`: `FileChange::getLines()`, which returns them as arrays, + is deprecated, as the `FileChange::LINE_*` constants and + `FileChange::getCount()`, replaced by `getAdditions()` and + `getDeletions()`. The constructor of `FileChange` takes `DiffLine` + objects: arrays are deprecated. Before: @@ -249,12 +324,12 @@ Diffs } ``` - After: + After, with 1.7 and 2.0: ```php use Gitonomy\Git\Diff\DiffLineType; - foreach ($change->getLines() as $line) { + foreach ($change->getDiffLines() as $line) { if (DiffLineType::Addition === $line->getType()) { // ... $line->getContent() } @@ -273,6 +348,13 @@ Diffs `git diff --raw --patch`, with `-z` or not. It reads the names of the files from the raw information: names with spaces are no longer split at the wrong place. +* It reads the status of a file, a creation, a modification, a deletion, + a rename..., from its raw line (`A`, `M`, `D`, `R100`...), instead of + the headers of the patch (`new file mode`...): a diff written by hand + where they disagree gives another result. Like git, the raw line + separates the status and the name with a TAB: spaces throw a + `RuntimeException`. Generate the diffs of your tests with git, with + `git diff --raw --patch --full-index`, instead of writing them. * During a merge conflict, `WorkingCopy::getDiffPending()` and `getDiffStaged()` leave the unmerged files out, where they threw, and `WorkingCopy::getDiff()` compares them, conflict markers included, to the @@ -295,12 +377,30 @@ Blame Trees ----- -* `Tree::getEntries()`, `getTreeEntries()`, `getBlobEntries()` and - `getSubmoduleEntries()` return `TreeEntry` objects, with `getName()`, - `getMode()` and `getObject()`: reading them as arrays - (`[$mode, $object]`) is deprecated. +* Iterating a `Tree` gives its entries by name, `TreeEntry` objects with + `getName()`, `getMode()` and `getObject()`; `getBlobs()`, `getTrees()` + and `getSubmodules()` return them by kind. `getEntries()`, + `getBlobEntries()` and `getTreeEntries()`, which return them as arrays + (`[$mode, $object]`), are deprecated. + + Before: + + ```php + foreach ($tree->getEntries() as $name => [$mode, $object]) { + // ... + } + ``` + + After, with 1.7 and 2.0: + + ```php + foreach ($tree as $name => $entry) { + // ... $entry->getMode(), $entry->getObject() + } + ``` + * `CommitReference` is deprecated: it is `Submodule`. So is - `Tree::getCommitReferenceEntries()`: use `getSubmoduleEntries()`. + `Tree::getCommitReferenceEntries()`: use `getSubmodules()`. * `Tree::resolvePath()` throws an `InvalidArgumentException` explaining why a path doesn't resolve, a path through a submodule included, which threw an `UnexpectedValueException`, and resolves `/` to the tree. @@ -409,7 +509,9 @@ Errors writes on its output (`CONFLICT (content): ...`). The command line, the rest of the error output and the output are no longer in the message: `getErrorOutput()` and `getOutput()` return the outputs of git. Its - constructor takes the git command as second argument, optional. + constructor takes the git command as second argument, optional, and + reads the exit code and the outputs of the `Process`: a test double of + `Process` must return them. * When git can't start, a missing binary for instance, `CliDriver` throws a `DriverException` instead of a `ProcessException`, with a message of one line, without the command line: `The git command "clone" could not @@ -419,9 +521,8 @@ Errors failed; * `ReferenceBag` (`Repository::getReferences()`) only returns an empty bag for a repository without references, and throws for any other failure. -* `Gitonomy\Git\Exception\UnexpectedValueException` is deprecated: gitlib - no longer throws it. Catch `InvalidArgumentException` for - `Tree::resolvePath()`. +* gitlib no longer throws `Gitonomy\Git\Exception\UnexpectedValueException`: + catch `InvalidArgumentException` for `Tree::resolvePath()`. * `Commit::getShortHash()` throws a `ReferenceNotFoundException` for an unknown commit, instead of a `ProcessException`. * `Hooks` throws a `RuntimeException` when a hook exists already, or can't @@ -555,6 +656,27 @@ Extending gitlib be unserialized: clear such caches. `Diff::toArray()` and `Diff::fromArray()` remain compatible. +Testing code using gitlib +------------------------- + +The classes `final` in 2.0 can't be doubled: `createMock()` of PHPUnit, +Prophecy and Mockery refuse them ("Class "Gitonomy\Git\WorkingCopy" is +declared "final" and cannot be doubled", "could not reflect class +Gitonomy\Git\WorkingCopy as it is marked final"). Instead, from the +simplest: + +1. Construct the value objects: `Diff`, `Diff\File`, `Diff\FileChange` + and `Diff\DiffLine` have public constructors. `new Diff([new File(...)], + '')` works with 1.x too. +2. Parse the real output of git: `Diff::parse()` of + `git diff --raw --patch --full-index` (see [Diffs](#diffs)). +3. Use a real repository, in a temporary directory: + `Repository::init($path)`, or `git init` with 1.x before 1.7. A + `WorkingCopy` needs one. +4. Implement `Gitonomy\Git\Driver\DriverInterface`, and pass it as the + driver of `Repository`: see + ["Using your own driver"](doc/repository.md#using-your-own-driver). + Data returned ------------- @@ -590,9 +712,20 @@ Data returned Other changes ------------- -* Relative paths, in the arguments of `Repository::run()` and in the paths - of a log, are relative to the repository instead of the current directory - of PHP. +* `Repository::run()` and `runProcess()` run git in the working directory + of the repository, or its git directory when it is bare, instead of the + current directory of PHP. Relative paths, in the arguments of `run()` + and in the paths of a log, are relative to the repository. When PHP runs + in a subdirectory of the repository, the output of the commands relative + to the current directory changes too, and so does their default scope: + + | `run()` in `repository/sub` | 1.x | 2.0 | + |------------------------------|-------------------|-------------------------------| + | `ls-files` | `in-sub.txt` | `root.txt`, `sub/in-sub.txt` | + | `status --short` | ` M ../root.txt` | ` M root.txt` | + | `rev-parse --show-prefix` | `sub/` | (empty) | + + Nothing changes when PHP runs out of the repository. * `Hooks::set()` makes hooks executable by their owner only (`0700`, instead of `0777`): change their permissions if another user runs them. * `Repository::shell()` is deprecated: it ignored the driver. Run diff --git a/composer.json b/composer.json index 38d97964..42bdc86b 100644 --- a/composer.json +++ b/composer.json @@ -55,5 +55,10 @@ "config": { "preferred-install": "dist", "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-main": "2.0.x-dev" + } } } diff --git a/doc/admin.md b/doc/admin.md index 3159199b..5ba076fe 100644 --- a/doc/admin.md +++ b/doc/admin.md @@ -2,7 +2,7 @@ Create and access git repositories ================================== The static methods of `Repository` create new repositories, and return them. -They replace `Admin`, deprecated since 2.0: see +They replace `Admin`, deprecated since 1.7: see [UPGRADE-2.0.md](../UPGRADE-2.0.md#creating-repositories). To open a repository that exists already, use `new Repository($path)`: see diff --git a/doc/blame.md b/doc/blame.md index 37556af0..9b24da4e 100644 --- a/doc/blame.md +++ b/doc/blame.md @@ -26,7 +26,7 @@ throws a `DriverException`. A last line before the first one blames the lines in order, like `git blame -L 5,3`. Passing a range as a string (`'2,3'` or `'2,+2'`, like `git blame -L`) is -deprecated since 2.0: pass the first and the last lines instead. +deprecated since 1.7: pass the first and the last lines instead. Line-per-line iteration ----------------------- @@ -66,7 +66,7 @@ $line->getCommit(); // The commit that last changed it $author = $line->getCommit()->getAuthorName(); ``` -`Line::getLine()` is deprecated since 2.0: use `getOriginalNumber()`, which +`Line::getLine()` is deprecated since 1.7: use `getOriginalNumber()`, which returns an integer. Group reading by commit @@ -87,4 +87,4 @@ foreach ($blame->getHunks() as $hunk) { } ``` -`getGroupedLines()` is deprecated since 2.0: use `getHunks()`. +`getGroupedLines()` is deprecated since 1.7: use `getHunks()`. diff --git a/doc/branch.md b/doc/branch.md index 7752e2c8..42879169 100644 --- a/doc/branch.md +++ b/doc/branch.md @@ -41,7 +41,7 @@ $branch = $branch->moveTo('master~2'); ``` Like `git update-ref`, it doesn't touch the working tree, even for the -branch checked out. `ReferenceBag::update()` is deprecated since 2.0: use +branch checked out. `ReferenceBag::update()` is deprecated since 1.7: use `moveTo()`. Merged branches @@ -56,7 +56,7 @@ if ($branch->isMergedInto('master')) { } ``` -`isMergedTo()` is deprecated since 2.0: use `isMergedInto()`, which has no +`isMergedTo()` is deprecated since 1.7: use `isMergedInto()`, which has no default destination (`master`) nor flag to compare remote branches only. Branches containing a commit diff --git a/doc/commit.md b/doc/commit.md index 5b06c423..aac1dfca 100644 --- a/doc/commit.md +++ b/doc/commit.md @@ -30,7 +30,7 @@ $commit->getHash(); // "7e9ba14939b0ce67ab95d83e03bd64710db91ef4" $commit->getShortHash(); // "7e9ba14", abbreviated and unique in the repository ``` -`getFixedShortHash()` is deprecated since 2.0: use +`getFixedShortHash()` is deprecated since 1.7: use `substr($commit->getHash(), 0, 6)`. Browsing parents @@ -125,7 +125,7 @@ the subject is `"Fix the parser of dates"`, and the body `"It failed on leap years.\n"`. A message without an empty line has no body. -`getShortMessage()` is deprecated since 2.0: truncate the subject with +`getShortMessage()` is deprecated since 1.7: truncate the subject with `symfony/string`, a dependency of gitlib, instead: ```php @@ -197,4 +197,4 @@ $remoteBranches = array_filter($branches, static fn (Branch $branch): bool => $b ``` Passing arguments to `getIncludingBranches()`, to keep the local or the -remote branches only, is deprecated since 2.0. +remote branches only, is deprecated since 1.7. diff --git a/doc/diff.md b/doc/diff.md index 75fcd95a..e474f5f3 100644 --- a/doc/diff.md +++ b/doc/diff.md @@ -25,7 +25,7 @@ $diff = $repository->getDiff($repository->getMergeBase('master', 'feature'), 'fe Calling `getDiff()` with one argument (a range like `a..b` or `a...b`, two revisions in an array, or one revision to compare with the working tree) -is deprecated since 2.0: see [UPGRADE-2.0.md](../UPGRADE-2.0.md). +is deprecated since 1.7: see [UPGRADE-2.0.md](../UPGRADE-2.0.md). `Log::getDiff()` is deprecated too: it ignored the paths of the log. Other diffs @@ -126,15 +126,15 @@ $file->getDeletions(); $file->getChanges(); // FileChange objects: see below ``` -`isChangeMode()`, `isDelete()` and `getAnchor()` are deprecated since 2.0: +`isChangeMode()`, `isDelete()` and `getAnchor()` are deprecated since 1.7: use `isModeChange()`, `isDeletion()` and `substr($file->getNewIndex(), 0, 12)`. The FileChange object --------------------- The changes of a file are its hunks, the blocks starting with `@@` in a -patch. Each one is a `FileChange` object, with the lines of the hunk, -`DiffLine` objects: +patch. Each one is a `FileChange` object: `getDiffLines()` returns the lines +of the hunk, `DiffLine` objects: ```php use Gitonomy\Git\Diff\DiffLineType; @@ -142,7 +142,7 @@ use Gitonomy\Git\Diff\DiffLineType; foreach ($file->getChanges() as $change) { echo sprintf('@@ -%d,%d +%d,%d @@', $change->getRangeOldStart(), $change->getRangeOldCount(), $change->getRangeNewStart(), $change->getRangeNewCount()).PHP_EOL; - foreach ($change->getLines() as $line) { + foreach ($change->getDiffLines() as $line) { echo match ($line->getType()) { DiffLineType::Addition => '+', DiffLineType::Context => ' ', @@ -164,10 +164,12 @@ foreach ($file->getChanges() as $change) { `getAdditions()` and `getDeletions()` count the lines the hunk adds and deletes. -Reading a line as an array (`[$type, $content]`), the `FileChange::LINE_ADD`, -`LINE_CONTEXT` and `LINE_REMOVE` constants, and `FileChange::getCount()` are -deprecated since 2.0: use `getType()` and `getContent()`, `DiffLineType`, -and `getAdditions()` or `getDeletions()`. +`getLines()`, which returns each line as an array (`[$type, $content]`), the +`FileChange::LINE_ADD`, `LINE_CONTEXT` and `LINE_REMOVE` constants, and +`FileChange::getCount()` are deprecated since 1.7: use `getDiffLines()`, +`DiffLineType`, and `getAdditions()` or `getDeletions()`. So is passing the +lines to the constructor of `FileChange` as arrays: pass `DiffLine` +objects. Parsing a diff -------------- @@ -211,5 +213,5 @@ $diff = Diff::fromArray($array, $repository); The arrays of 1.x are read too. `Diff::setRepository()`, `File::setRepository()` and `File::addChange()` are -deprecated since 2.0: pass the repository to `Diff::parse()` or +deprecated since 1.7: pass the repository to `Diff::parse()` or `Diff::fromArray()`, and the changes to the constructor of `File`. diff --git a/doc/log.md b/doc/log.md index ceb9df81..1cd66947 100644 --- a/doc/log.md +++ b/doc/log.md @@ -138,5 +138,5 @@ $secondPage->getLimit(); // 10 Diff of a log ------------- -`Log::getDiff()` is deprecated since 2.0: it ignored the paths of the log. +`Log::getDiff()` is deprecated since 1.7: it ignored the paths of the log. Use `Repository::getDiff($from, $to)`, see [diff.md](diff.md). diff --git a/doc/references.md b/doc/references.md index 9feb1de7..adab71f6 100644 --- a/doc/references.md +++ b/doc/references.md @@ -14,7 +14,7 @@ $references = $repository->getReferences(); The bag reads the references again after every write gitlib makes: creating or deleting a reference, a checkout, a merge, `Repository::run()`... To see the writes of other processes, open a new `Repository`. Passing an argument -to `getReferences()`, to read them again, is deprecated since 2.0. +to `getReferences()`, to read them again, is deprecated since 1.7. First, you can test the existence of tags and branches like this: @@ -110,7 +110,7 @@ like `refs/heads/foobar`, and does nothing when it doesn't exist, like `createBranch()` and `createTag()` throw an `InvalidArgumentException` when the reference exists: they never move it. To move a branch, use `Branch::moveTo()`: see [branch.md](branch.md). `ReferenceBag::update()` is -deprecated since 2.0: use `Branch::moveTo()`. +deprecated since 1.7: use `Branch::moveTo()`. Tags ---- diff --git a/doc/repository.md b/doc/repository.md index 0864ed5f..a81e85de 100644 --- a/doc/repository.md +++ b/doc/repository.md @@ -47,7 +47,7 @@ $repository = new Repository('/srv/project.git', '/srv/project', new CliDriver(p ``` An array of options as second argument (`working_dir`, `logger`, `command`, -`process_timeout`...) is deprecated since 2.0: pass the working directory, +`process_timeout`...) is deprecated since 1.7: pass the working directory, and configure a `CliDriver` instead. See [UPGRADE-2.0.md](../UPGRADE-2.0.md#opening-a-repository). @@ -151,7 +151,7 @@ gitlib reads them again after every write it makes: creating or deleting a reference, a checkout, a merge, `run()`... It doesn't see the writes of other processes (a push to the repository, another worker...): open a new `Repository` to see them. The `$reload` argument of `getReferences()` is -deprecated since 2.0. +deprecated since 1.7. Description ----------- @@ -176,7 +176,7 @@ $size = $repository->getSizeInBytes(); echo 'Your repository size is '.round($size / 1000).' KB'; ``` -`getSize()`, which returns kilobytes (1,000 bytes), is deprecated since 2.0: +`getSize()`, which returns kilobytes (1,000 bytes), is deprecated since 1.7: use `getSizeInBytes()`. Running git commands @@ -208,7 +208,7 @@ your users starting with a dash is an option for git, unless `--` comes before it. gitlib reads the references again after the command, which may have written them. -`shell()` is deprecated since 2.0: run `git shell` with Symfony Process +`shell()` is deprecated since 1.7: run `git shell` with Symfony Process instead. Errors @@ -481,7 +481,7 @@ $repository = new Repository('/tmp/foo', driver: new CliDriver( ``` The `command`, `environment_variables` and `process_timeout` options of -`Repository` and `Admin`, from 1.x, are deprecated since 2.0 in favor of these +`Repository` and `Admin`, from 1.x, are deprecated since 1.7 in favor of these arguments. So is `inherit_environment_variables`, which passed the entries of `$_SERVER` to git, the headers and credentials of an HTTP request included: pass the variables git needs to `environmentVariables`. diff --git a/doc/tree.md b/doc/tree.md index 47abe374..21451d12 100644 --- a/doc/tree.md +++ b/doc/tree.md @@ -14,13 +14,13 @@ $tree = $commit->getTree(); Entries of a tree ----------------- -`getEntries()` returns the entries of a tree, keyed by their name. Each one -is a `TreeEntry` object, with the name of the entry, its mode, and its -object: a `Blob` for a file (see [blob.md](blob.md)), a `Tree` for a folder, -or a `Submodule`. +Iterating a tree gives its entries, keyed by their name. Each one is a +`TreeEntry` object, with the name of the entry, its mode, and its object: a +`Blob` for a file (see [blob.md](blob.md)), a `Tree` for a folder, or a +`Submodule`. ```php -foreach ($tree->getEntries() as $name => $entry) { +foreach ($tree as $name => $entry) { $entry->getName(); // The name of the file or the folder, the same as $name $entry->getMode(); // The mode git stores: "100644", "100755" (executable), "120000" (symbolic link), "040000" (tree), "160000" (submodule) $entry->getObject(); // A Blob, a Tree or a Submodule @@ -30,9 +30,9 @@ foreach ($tree->getEntries() as $name => $entry) { To keep one kind of entries only, also keyed by their name: ```php -$folders = $tree->getTreeEntries(); -$files = $tree->getBlobEntries(); -$submodules = $tree->getSubmoduleEntries(); +$files = $tree->getBlobs(); +$submodules = $tree->getSubmodules(); +$folders = $tree->getTrees(); ``` To get the object of an entry by its name: @@ -51,7 +51,7 @@ use Gitonomy\Git\Tree; function displayTree(Tree $tree, int $depth = 0): void { - foreach ($tree->getEntries() as $name => $entry) { + foreach ($tree as $name => $entry) { $object = $entry->getObject(); echo str_repeat(' ', $depth).match (true) { @@ -69,8 +69,9 @@ function displayTree(Tree $tree, int $depth = 0): void displayTree($commit->getTree()); ``` -Reading an entry as an array (`[$mode, $object]`) is deprecated since 2.0: -use `getMode()` and `getObject()`. +`getEntries()`, `getBlobEntries()` and `getTreeEntries()`, which return +the mode and the object of each entry as an array (`[$mode, $object]`), are +deprecated since 1.7: iterate the tree, or use `getBlobs()` and `getTrees()`. Submodules ---------- @@ -80,13 +81,13 @@ holds the hash of this commit: gitlib doesn't read the submodule. Open it as a repository, from its folder in the working tree, to read it. ```php -foreach ($tree->getSubmoduleEntries() as $name => $entry) { +foreach ($tree->getSubmodules() as $name => $entry) { echo $name.' is at '.$entry->getObject()->getHash().PHP_EOL; } ``` -`CommitReference` is deprecated since 2.0: it is `Submodule`. So is -`Tree::getCommitReferenceEntries()`: use `getSubmoduleEntries()`. +`CommitReference` is deprecated since 1.7: it is `Submodule`. So is +`Tree::getCommitReferenceEntries()`: use `getSubmodules()`. Resolve a path -------------- diff --git a/doc/workingcopy.md b/doc/workingcopy.md index 2e02ae64..462c7a46 100644 --- a/doc/workingcopy.md +++ b/doc/workingcopy.md @@ -72,7 +72,7 @@ overwrite the ones the checkout would change: they throw a `DriverException`. *checkoutNewBranch* then creates no branch. Passing the branch to create as second argument of *checkout* is deprecated -since 2.0: use *checkoutNewBranch*. +since 1.7: use *checkoutNewBranch*. Merge a revision ---------------- @@ -132,7 +132,7 @@ $diff = $wc->getDiff('master'); ``` Calling `Repository::getDiff()` with one revision, to compare it with the -working copy, is deprecated since 2.0: use `WorkingCopy::getDiff()`. +working copy, is deprecated since 1.7: use `WorkingCopy::getDiff()`. Staged modifications -------------------- diff --git a/src/Gitonomy/Git/Admin.php b/src/Gitonomy/Git/Admin.php index 83e2d7b5..d29f7b57 100644 --- a/src/Gitonomy/Git/Admin.php +++ b/src/Gitonomy/Git/Admin.php @@ -25,7 +25,7 @@ * * @author Alexandre Salomé * - * @deprecated since gitonomy/gitlib 2.0, use the static methods of Repository instead + * @deprecated since gitonomy/gitlib 1.7, use the static methods of Repository instead * * @phpstan-import-type Options from LegacyOptions */ @@ -40,11 +40,11 @@ final class Admin * * @throws Exception\DriverException Directory exists or not writable * - * @deprecated since gitonomy/gitlib 2.0, use Repository::initBare() or Repository::init() instead + * @deprecated since gitonomy/gitlib 1.7, use Repository::initBare() or Repository::init() instead */ public static function init(string $path, bool $bare = true, array $options = []): Repository { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "%s::%s()" instead.', __METHOD__, Repository::class, $bare ? 'initBare' : 'init'); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "%s::%s()" instead.', __METHOD__, Repository::class, $bare ? 'initBare' : 'init'); $options = new LegacyOptions($options); $driver = $options->adminDriver() ?? new CliDriver(); @@ -69,11 +69,11 @@ public static function init(string $path, bool $bare = true, array $options = [] * * @return bool true if url is valid * - * @deprecated since gitonomy/gitlib 2.0, use Repository::isValidRepository() instead + * @deprecated since gitonomy/gitlib 1.7, use Repository::isValidRepository() instead */ public static function isValidRepository(#[\SensitiveParameter] string $url, array $options = []): bool { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "%s::isValidRepository()" instead.', __METHOD__, Repository::class); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "%s::isValidRepository()" instead.', __METHOD__, Repository::class); return (new LegacyOptions($options)->adminDriver() ?? new CliDriver())->isValidRepository($url); } @@ -92,11 +92,11 @@ public static function isValidRepository(#[\SensitiveParameter] string $url, arr * * @return bool true if url is valid and branch exists * - * @deprecated since gitonomy/gitlib 2.0, use Repository::isValidRepositoryAndBranch() instead + * @deprecated since gitonomy/gitlib 1.7, use Repository::isValidRepositoryAndBranch() instead */ public static function isValidRepositoryAndBranch(#[\SensitiveParameter] string $url, string $branchName, array $options = []): bool { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "%s::isValidRepositoryAndBranch()" instead.', __METHOD__, Repository::class); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "%s::isValidRepositoryAndBranch()" instead.', __METHOD__, Repository::class); return (new LegacyOptions($options)->adminDriver() ?? new CliDriver())->isValidRepositoryAndBranch($url, $branchName); } @@ -109,11 +109,11 @@ public static function isValidRepositoryAndBranch(#[\SensitiveParameter] string * @param bool $bare indicates if repository should be bare or have a working copy * @param Options $options options for Repository creation * - * @deprecated since gitonomy/gitlib 2.0, use Repository::cloneBareFrom() or Repository::cloneFrom() instead + * @deprecated since gitonomy/gitlib 1.7, use Repository::cloneBareFrom() or Repository::cloneFrom() instead */ public static function cloneTo(string $path, #[\SensitiveParameter] string $url, bool $bare = true, array $options = []): Repository { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "%s::%s()" instead, which takes the URL before the path.', __METHOD__, Repository::class, $bare ? 'cloneBareFrom' : 'cloneFrom'); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "%s::%s()" instead, which takes the URL before the path.', __METHOD__, Repository::class, $bare ? 'cloneBareFrom' : 'cloneFrom'); $options = new LegacyOptions($options); $driver = $options->adminDriver() ?? new CliDriver(); @@ -135,11 +135,11 @@ public static function cloneTo(string $path, #[\SensitiveParameter] string $url, * @param bool $bare indicates if repository should be bare or have a working copy * @param Options $options options for Repository creation * - * @deprecated since gitonomy/gitlib 2.0, use Repository::cloneBareFrom() or Repository::cloneFrom() with their "branch" argument instead + * @deprecated since gitonomy/gitlib 1.7, use Repository::cloneBareFrom() or Repository::cloneFrom() with their "branch" argument instead */ public static function cloneBranchTo(string $path, #[\SensitiveParameter] string $url, string $branch, bool $bare = true, array $options = []): Repository { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "%s::%s()" with its "branch" argument instead, which takes the URL before the path.', __METHOD__, Repository::class, $bare ? 'cloneBareFrom' : 'cloneFrom'); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "%s::%s()" with its "branch" argument instead, which takes the URL before the path.', __METHOD__, Repository::class, $bare ? 'cloneBareFrom' : 'cloneFrom'); $options = new LegacyOptions($options); $driver = $options->adminDriver() ?? new CliDriver(); @@ -159,11 +159,11 @@ public static function cloneBranchTo(string $path, #[\SensitiveParameter] string * @param string $url url of repository to clone * @param Options $options options for Repository creation * - * @deprecated since gitonomy/gitlib 2.0, use Repository::mirrorFrom() instead + * @deprecated since gitonomy/gitlib 1.7, use Repository::mirrorFrom() instead */ public static function mirrorTo(string $path, #[\SensitiveParameter] string $url, array $options = []): Repository { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "%s::mirrorFrom()" instead, which takes the URL before the path.', __METHOD__, Repository::class); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "%s::mirrorFrom()" instead, which takes the URL before the path.', __METHOD__, Repository::class); $options = new LegacyOptions($options); $driver = $options->adminDriver() ?? new CliDriver(); @@ -180,11 +180,11 @@ public static function mirrorTo(string $path, #[\SensitiveParameter] string $url * @param string[] $args arguments to be added to the command-line * @param Options $options options for Repository creation * - * @deprecated since gitonomy/gitlib 2.0, use Repository::cloneFrom(), Repository::cloneBareFrom() or Repository::mirrorFrom() instead + * @deprecated since gitonomy/gitlib 1.7, use Repository::cloneFrom(), Repository::cloneBareFrom() or Repository::mirrorFrom() instead */ public static function cloneRepository(string $path, #[\SensitiveParameter] string $url, array $args = [], array $options = []): Repository { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%1$s()" method is deprecated, use "%2$s::cloneFrom()", "%2$s::cloneBareFrom()" or "%2$s::mirrorFrom()" instead, which take the URL before the path; they support no other argument of "git clone".', __METHOD__, Repository::class); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%1$s()" method is deprecated, use "%2$s::cloneFrom()", "%2$s::cloneBareFrom()" or "%2$s::mirrorFrom()" instead, which take the URL before the path; they support no other argument of "git clone".', __METHOD__, Repository::class); $options = new LegacyOptions($options); $driver = $options->adminDriver() ?? new CliDriver(); diff --git a/src/Gitonomy/Git/Blame.php b/src/Gitonomy/Git/Blame.php index 009ce6ee..d9b31acd 100644 --- a/src/Gitonomy/Git/Blame.php +++ b/src/Gitonomy/Git/Blame.php @@ -92,11 +92,11 @@ public function getHunks(): array * * @return list}> * - * @deprecated since gitonomy/gitlib 2.0, use getHunks() instead + * @deprecated since gitonomy/gitlib 1.7, use getHunks() instead */ public function getGroupedLines(): array { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "getHunks()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "getHunks()" instead.', __METHOD__); return array_map(static fn (Hunk $hunk): array => [$hunk->getCommit(), $hunk->getLines()], $this->getHunks()); } diff --git a/src/Gitonomy/Git/Blame/Line.php b/src/Gitonomy/Git/Blame/Line.php index 6254b2cd..6bc8b01b 100644 --- a/src/Gitonomy/Git/Blame/Line.php +++ b/src/Gitonomy/Git/Blame/Line.php @@ -53,11 +53,11 @@ public function getOriginalNumber(): int } /** - * @deprecated since gitonomy/gitlib 2.0, use getOriginalNumber() instead + * @deprecated since gitonomy/gitlib 1.7, use getOriginalNumber() instead */ public function getLine(): string { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "getOriginalNumber()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "getOriginalNumber()" instead.', __METHOD__); return (string) $this->originalNumber; } diff --git a/src/Gitonomy/Git/Commit.php b/src/Gitonomy/Git/Commit.php index 22b1f29d..9b82f896 100644 --- a/src/Gitonomy/Git/Commit.php +++ b/src/Gitonomy/Git/Commit.php @@ -89,11 +89,11 @@ public function getShortHash(): string /** * Returns a fixed-with short hash. * - * @deprecated since gitonomy/gitlib 2.0, use substr($commit->getHash(), 0, $length) instead + * @deprecated since gitonomy/gitlib 1.7, use substr($commit->getHash(), 0, $length) instead */ public function getFixedShortHash(int $length = 6): string { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "substr($commit->getHash(), 0, $length)" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "substr($commit->getHash(), 0, $length)" instead.', __METHOD__); return new CodePointString($this->revision)->slice(0, $length)->toString(); } @@ -157,11 +157,11 @@ public function getLastModification(?string $path = null): self * * Ported from https://github.com/fabpot/Twig-extensions/blob/d67bc7e69788795d7905b52d31188bbc1d390e01/lib/Twig/Extensions/Extension/Text.php#L52-L109 * - * @deprecated since gitonomy/gitlib 2.0, use symfony/string instead: u($commit->getSubjectMessage())->truncate($length, $separator, !$preserve) + * @deprecated since gitonomy/gitlib 1.7, use symfony/string instead: u($commit->getSubjectMessage())->truncate($length, $separator, !$preserve) */ public function getShortMessage(int $length = 50, bool $preserve = false, string $separator = '...'): string { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use symfony/string instead: "u($commit->getSubjectMessage())->truncate($length, $separator, !$preserve)".', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use symfony/string instead: "u($commit->getSubjectMessage())->truncate($length, $separator, !$preserve)".', __METHOD__); $message = $this->getSubjectMessage(); @@ -198,7 +198,7 @@ public function resolveReferences(): array public function getIncludingBranches(bool $local = true, bool $remote = true): array { if (\func_num_args() > 0) { - trigger_deprecation('gitonomy/gitlib', '2.0', 'Passing arguments to "%s()" is deprecated, filter the branches it returns with "%s::isLocal()" or "isRemote()" instead.', __METHOD__, Branch::class); + trigger_deprecation('gitonomy/gitlib', '1.7', 'Passing arguments to "%s()" is deprecated, filter the branches it returns with "%s::isLocal()" or "isRemote()" instead.', __METHOD__, Branch::class); } if (!$local && !$remote) { diff --git a/src/Gitonomy/Git/CommitReference.php b/src/Gitonomy/Git/CommitReference.php index 5a10b217..01a6d55f 100644 --- a/src/Gitonomy/Git/CommitReference.php +++ b/src/Gitonomy/Git/CommitReference.php @@ -12,7 +12,7 @@ namespace Gitonomy\Git; -trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s" class is deprecated, use "%s" instead.', CommitReference::class, Submodule::class); +trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s" class is deprecated, use "%s" instead.', CommitReference::class, Submodule::class); // Declares the alias, unless Submodule already did. class_exists(Submodule::class); @@ -20,7 +20,7 @@ class_exists(Submodule::class); // @phpstan-ignore if.alwaysFalse (Declares the class for IDEs only.) if (false) { /** - * @deprecated since gitonomy/gitlib 2.0, use Submodule instead + * @deprecated since gitonomy/gitlib 1.7, use Submodule instead */ final readonly class CommitReference { diff --git a/src/Gitonomy/Git/Diff/Diff.php b/src/Gitonomy/Git/Diff/Diff.php index bb26cc61..4abd4347 100644 --- a/src/Gitonomy/Git/Diff/Diff.php +++ b/src/Gitonomy/Git/Diff/Diff.php @@ -62,11 +62,11 @@ public static function fromData(DiffData $data, Repository $repository): self } /** - * @deprecated since gitonomy/gitlib 2.0, the diffs gitlib returns have their repository already + * @deprecated since gitonomy/gitlib 1.7, the diffs gitlib returns have their repository already */ public function setRepository(Repository $repository): void { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, the diffs gitlib returns have their repository already.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, the diffs gitlib returns have their repository already.', __METHOD__); foreach ($this->files as $file) { // Without one more deprecation for each file. diff --git a/src/Gitonomy/Git/Diff/DiffLine.php b/src/Gitonomy/Git/Diff/DiffLine.php index 303d8bc9..ddb1a59a 100644 --- a/src/Gitonomy/Git/Diff/DiffLine.php +++ b/src/Gitonomy/Git/Diff/DiffLine.php @@ -12,20 +12,12 @@ namespace Gitonomy\Git\Diff; -use Gitonomy\Git\Exception\InvalidArgumentException; -use Gitonomy\Git\Exception\LogicException; - /** * A line of a hunk. * - * Reading it as an array, [$type, $content] with the type as one of the - * FileChange::LINE_* constants, is deprecated. - * * @author Grégoire Pineau - * - * @implements \ArrayAccess */ -final readonly class DiffLine implements \ArrayAccess +final readonly class DiffLine { public function __construct( private DiffLineType $type, @@ -45,33 +37,4 @@ public function getContent(): string { return $this->content; } - - public function offsetExists(mixed $offset): bool - { - return 0 === $offset || 1 === $offset; - } - - /** - * @deprecated since gitonomy/gitlib 2.0, use getType() and getContent() instead - */ - public function offsetGet(mixed $offset): int|string - { - trigger_deprecation('gitonomy/gitlib', '2.0', 'Reading a "%s" as an array is deprecated, use its "getType()" and "getContent()" methods instead.', self::class); - - return match ($offset) { - 0 => $this->type->value, - 1 => $this->content, - default => throw new InvalidArgumentException(\sprintf('A diff line has no offset %s.', var_export($offset, true))), - }; - } - - public function offsetSet(mixed $offset, mixed $value): void - { - throw new LogicException('A diff line is immutable.'); - } - - public function offsetUnset(mixed $offset): void - { - throw new LogicException('A diff line is immutable.'); - } } diff --git a/src/Gitonomy/Git/Diff/File.php b/src/Gitonomy/Git/Diff/File.php index 516195b9..c18e2cd3 100644 --- a/src/Gitonomy/Git/Diff/File.php +++ b/src/Gitonomy/Git/Diff/File.php @@ -56,11 +56,11 @@ public function __construct( } /** - * @deprecated since gitonomy/gitlib 2.0, give the changes to the constructor instead + * @deprecated since gitonomy/gitlib 1.7, give the changes to the constructor instead */ public function addChange(FileChange $change): void { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, give the changes to the constructor instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, give the changes to the constructor instead.', __METHOD__); $this->changes[] = $change; } @@ -110,11 +110,11 @@ public function isModeChange(): bool } /** - * @deprecated since gitonomy/gitlib 2.0, use isModeChange() instead + * @deprecated since gitonomy/gitlib 1.7, use isModeChange() instead */ public function isChangeMode(): bool { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "isModeChange()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "isModeChange()" instead.', __METHOD__); return $this->isModeChange(); } @@ -128,11 +128,11 @@ public function isDeletion(): bool } /** - * @deprecated since gitonomy/gitlib 2.0, use isDeletion() instead + * @deprecated since gitonomy/gitlib 1.7, use isDeletion() instead */ public function isDelete(): bool { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "isDeletion()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "isDeletion()" instead.', __METHOD__); return $this->isDeletion(); } @@ -251,11 +251,11 @@ public static function fromArray(array $array, ?Repository $repository = null): } /** - * @deprecated since gitonomy/gitlib 2.0, a presentation concern: use substr($file->getNewIndex(), 0, 12) instead + * @deprecated since gitonomy/gitlib 1.7, a presentation concern: use substr($file->getNewIndex(), 0, 12) instead */ public function getAnchor(): string { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "substr($file->getNewIndex(), 0, 12)" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "substr($file->getNewIndex(), 0, 12)" instead.', __METHOD__); return substr($this->newIndex ?? '', 0, 12); } @@ -266,11 +266,11 @@ public function getRepository(): ?Repository } /** - * @deprecated since gitonomy/gitlib 2.0, the diffs gitlib returns have their repository already + * @deprecated since gitonomy/gitlib 1.7, the diffs gitlib returns have their repository already */ public function setRepository(Repository $repository): void { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, the diffs gitlib returns have their repository already.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, the diffs gitlib returns have their repository already.', __METHOD__); $this->repository = $repository; } diff --git a/src/Gitonomy/Git/Diff/FileChange.php b/src/Gitonomy/Git/Diff/FileChange.php index 08f28236..20f02e7e 100644 --- a/src/Gitonomy/Git/Diff/FileChange.php +++ b/src/Gitonomy/Git/Diff/FileChange.php @@ -22,38 +22,50 @@ final readonly class FileChange { /** - * @deprecated since gitonomy/gitlib 2.0, use DiffLineType::Context instead + * @deprecated since gitonomy/gitlib 1.7, use DiffLineType::Context instead */ public const int LINE_CONTEXT = 0; /** - * @deprecated since gitonomy/gitlib 2.0, use DiffLineType::Deletion instead + * @deprecated since gitonomy/gitlib 1.7, use DiffLineType::Deletion instead */ public const int LINE_REMOVE = -1; /** - * @deprecated since gitonomy/gitlib 2.0, use DiffLineType::Addition instead + * @deprecated since gitonomy/gitlib 1.7, use DiffLineType::Addition instead */ public const int LINE_ADD = 1; /** - * @param DiffLine[] $lines + * @var list + */ + private array $lines; + + /** + * @param array $lines Passing arrays is deprecated + * + * @throws InvalidArgumentException An array has none of the types of line */ public function __construct( private int $rangeOldStart, private int $rangeOldCount, private int $rangeNewStart, private int $rangeNewCount, - private array $lines, + array $lines, ) { + if ([] !== array_filter($lines, is_array(...))) { + trigger_deprecation('gitonomy/gitlib', '1.7', 'Passing the lines to "%s()" as arrays is deprecated, pass "%s" objects instead.', __METHOD__, DiffLine::class); + } + + $this->lines = array_map(static fn (DiffLine|array $line): DiffLine => \is_array($line) ? new DiffLine(self::lineType($line[0]), $line[1]) : $line, array_values($lines)); } /** - * @deprecated since gitonomy/gitlib 2.0, use getAdditions() or getDeletions() instead + * @deprecated since gitonomy/gitlib 1.7, use getAdditions() or getDeletions() instead */ public function getCount(int $type): int { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "getAdditions()" or "getDeletions()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "getAdditions()" or "getDeletions()" instead.', __METHOD__); return $this->count(self::lineType($type)); } @@ -89,13 +101,25 @@ public function getRangeNewCount(): int } /** - * @return DiffLine[] + * @return list */ - public function getLines(): array + public function getDiffLines(): array { return $this->lines; } + /** + * @return list The type of each line, one of the LINE_* constants, and its content + * + * @deprecated since gitonomy/gitlib 1.7, use getDiffLines() instead + */ + public function getLines(): array + { + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "getDiffLines()" instead.', __METHOD__); + + return $this->linesToArray(); + } + /** * @return FileChangeArray */ @@ -106,7 +130,7 @@ public function toArray(): array 'range_old_count' => $this->rangeOldCount, 'range_new_start' => $this->rangeNewStart, 'range_new_count' => $this->rangeNewCount, - 'lines' => array_map(static fn (DiffLine $line): array => [$line->getType()->value, $line->getContent()], array_values($this->lines)), + 'lines' => $this->linesToArray(), ]; } @@ -125,15 +149,23 @@ public static function fromArray(array $array): self } /** - * @throws InvalidArgumentException $type is none of the LINE_* constants + * @throws InvalidArgumentException $type is none of the values of DiffLineType */ private static function lineType(int $type): DiffLineType { - return DiffLineType::tryFrom($type) ?? throw new InvalidArgumentException(\sprintf('Unknown type of line %d: the types are FileChange::LINE_ADD, LINE_CONTEXT and LINE_REMOVE.', $type)); + return DiffLineType::tryFrom($type) ?? throw new InvalidArgumentException(\sprintf('Unknown type of line %d: the types are 1 (an addition), 0 (a context line) and -1 (a deletion).', $type)); } private function count(DiffLineType $type): int { return \count(array_filter($this->lines, static fn (DiffLine $line): bool => $line->getType() === $type)); } + + /** + * @return list + */ + private function linesToArray(): array + { + return array_map(static fn (DiffLine $line): array => [$line->getType()->value, $line->getContent()], $this->lines); + } } diff --git a/src/Gitonomy/Git/Exception/UnexpectedValueException.php b/src/Gitonomy/Git/Exception/UnexpectedValueException.php index cfe3e4c3..a9abcaa1 100644 --- a/src/Gitonomy/Git/Exception/UnexpectedValueException.php +++ b/src/Gitonomy/Git/Exception/UnexpectedValueException.php @@ -13,7 +13,8 @@ namespace Gitonomy\Git\Exception; /** - * @deprecated since gitonomy/gitlib 2.0, gitlib no longer throws it: Tree::resolvePath(), which threw it in 1.x, throws an InvalidArgumentException instead + * gitlib no longer throws it: Tree::resolvePath(), which threw it in 1.x, + * throws an InvalidArgumentException instead. */ final class UnexpectedValueException extends \UnexpectedValueException implements GitExceptionInterface { diff --git a/src/Gitonomy/Git/Log.php b/src/Gitonomy/Git/Log.php index c099e0be..1f4eddb7 100644 --- a/src/Gitonomy/Git/Log.php +++ b/src/Gitonomy/Git/Log.php @@ -72,11 +72,11 @@ public function __construct( } /** - * @deprecated since gitonomy/gitlib 2.0, use Repository::getDiff() instead: it ignored the paths of the log + * @deprecated since gitonomy/gitlib 1.7, use Repository::getDiff() instead: it ignored the paths of the log */ public function getDiff(): Diff { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "%s::getDiff()" instead.', __METHOD__, Repository::class); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "%s::getDiff()" instead.', __METHOD__, Repository::class); return $this->repository->getLegacyDiff($this->revisions); } @@ -113,11 +113,11 @@ public function withOffset(?int $offset): self } /** - * @deprecated since gitonomy/gitlib 2.0, use withOffset() instead + * @deprecated since gitonomy/gitlib 1.7, use withOffset() instead */ public function setOffset(?int $offset): static { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "withOffset()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "withOffset()" instead.', __METHOD__); $this->offset = self::offset($offset); @@ -143,11 +143,11 @@ public function withLimit(?int $limit): self } /** - * @deprecated since gitonomy/gitlib 2.0, use withLimit() instead + * @deprecated since gitonomy/gitlib 1.7, use withLimit() instead */ public function setLimit(?int $limit): static { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "withLimit()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "withLimit()" instead.', __METHOD__); $this->limit = self::limit($limit); diff --git a/src/Gitonomy/Git/PushReference.php b/src/Gitonomy/Git/PushReference.php index 4cf81c1c..0efdde24 100644 --- a/src/Gitonomy/Git/PushReference.php +++ b/src/Gitonomy/Git/PushReference.php @@ -53,11 +53,11 @@ public function getFullname(): string } /** - * @deprecated since gitonomy/gitlib 2.0, use getFullname() instead + * @deprecated since gitonomy/gitlib 1.7, use getFullname() instead */ public function getReference(): string { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "getFullname()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "getFullname()" instead.', __METHOD__); return $this->fullname; } @@ -81,11 +81,11 @@ public function getLog(array $excludes = []): Log } /** - * @deprecated since gitonomy/gitlib 2.0, use getRange() instead + * @deprecated since gitonomy/gitlib 1.7, use getRange() instead */ public function getRevision(): string { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "getRange()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "getRange()" instead.', __METHOD__); return $this->getRange(); } @@ -117,11 +117,11 @@ public function isCreation(): bool } /** - * @deprecated since gitonomy/gitlib 2.0, use isCreation() instead + * @deprecated since gitonomy/gitlib 1.7, use isCreation() instead */ public function isCreate(): bool { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "isCreation()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "isCreation()" instead.', __METHOD__); return $this->isCreation(); } @@ -135,11 +135,11 @@ public function isDeletion(): bool } /** - * @deprecated since gitonomy/gitlib 2.0, use isDeletion() instead + * @deprecated since gitonomy/gitlib 1.7, use isDeletion() instead */ public function isDelete(): bool { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "isDeletion()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "isDeletion()" instead.', __METHOD__); return $this->isDeletion(); } diff --git a/src/Gitonomy/Git/Reference/Branch.php b/src/Gitonomy/Git/Reference/Branch.php index 1ac791da..5ee7ef42 100644 --- a/src/Gitonomy/Git/Reference/Branch.php +++ b/src/Gitonomy/Git/Reference/Branch.php @@ -62,11 +62,11 @@ public function isMergedInto(Revision|string $revision): bool * Check if this branch is merged to a destination branch * Optionally, check only with remote branches. * - * @deprecated since gitonomy/gitlib 2.0, use isMergedInto() instead + * @deprecated since gitonomy/gitlib 1.7, use isMergedInto() instead */ public function isMergedTo(string $destinationBranchName = 'master', bool $compareOnlyWithRemote = false): bool { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "%s::isMergedInto()" instead.', __METHOD__, self::class); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "%s::isMergedInto()" instead.', __METHOD__, self::class); if ($compareOnlyWithRemote && $this->isLocal()) { return false; diff --git a/src/Gitonomy/Git/ReferenceBag.php b/src/Gitonomy/Git/ReferenceBag.php index 530d7828..8790f609 100644 --- a/src/Gitonomy/Git/ReferenceBag.php +++ b/src/Gitonomy/Git/ReferenceBag.php @@ -65,11 +65,11 @@ public function has(string $fullname): bool * * @return T * - * @deprecated since gitonomy/gitlib 2.0, use Branch::moveTo() instead + * @deprecated since gitonomy/gitlib 1.7, use Branch::moveTo() instead */ public function update(Reference $reference): Reference { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "%s::moveTo()" instead.', __METHOD__, Branch::class); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "%s::moveTo()" instead.', __METHOD__, Branch::class); $this->repository->getRepositoryDriver()->updateReference($reference->getFullname(), $reference->getCommitHash()); $this->invalidate(); diff --git a/src/Gitonomy/Git/Repository.php b/src/Gitonomy/Git/Repository.php index 6b9ca6bd..22fd984c 100644 --- a/src/Gitonomy/Git/Repository.php +++ b/src/Gitonomy/Git/Repository.php @@ -109,7 +109,7 @@ final class Repository public function __construct(string $dir, array|string|null $workingDir = null, DriverInterface $driver = new CliDriver()) { if (\is_array($workingDir)) { - trigger_deprecation('gitonomy/gitlib', '2.0', 'Passing an array of options to "%s()" is deprecated, pass the working directory as "workingDir" argument, and configure the logger and git through the "driver" argument.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'Passing an array of options to "%s()" is deprecated, pass the working directory as "workingDir" argument, and configure the logger and git through the "driver" argument.', __METHOD__); $options = new LegacyOptions($workingDir); $optionsDriver = $options->repositoryDriver(); @@ -338,7 +338,7 @@ public function getReferences(bool $reload = false): ReferenceBag $this->referenceBag ??= new ReferenceBag($this); if (\func_num_args() > 0) { - trigger_deprecation('gitonomy/gitlib', '2.0', 'Passing an argument to "%s()" is deprecated, gitlib reads the references again after its writes: open a new Repository to see the writes of other processes.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'Passing an argument to "%s()" is deprecated, gitlib reads the references again after its writes: open a new Repository to see the writes of other processes.', __METHOD__); } if ($reload) { @@ -428,7 +428,7 @@ public function getMergeBase(Revision|string $one, Revision|string $two): ?Commi public function getBlame(Revision|string $revision, string $file, int|string|null $firstLine = null, ?int $lastLine = null): Blame { if (\is_string($firstLine)) { - trigger_deprecation('gitonomy/gitlib', '2.0', 'Passing a range of lines as a string to "%s()" is deprecated, pass the first and the last lines instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'Passing a range of lines as a string to "%s()" is deprecated, pass the first and the last lines instead.', __METHOD__); if (!preg_match('/^(\d+),(\+?)(\d*)$/', $firstLine, $vars)) { throw new InvalidArgumentException(\sprintf('Unsupported range of lines "%s": pass the first and the last lines instead.', $firstLine)); @@ -476,7 +476,7 @@ public function getLog(RevisionList|Revision|string|array|null $revisions = null public function getDiff(RevisionList|Revision|string|array|null $from, Revision|string|null $to = null): Diff { if (null === $to) { - trigger_deprecation('gitonomy/gitlib', '2.0', 'Calling "%s()" with one argument is deprecated, pass the revisions to compare as "from" and "to" arguments, or use "%s::getDiff()" to compare a revision with the working tree.', __METHOD__, WorkingCopy::class); + trigger_deprecation('gitonomy/gitlib', '1.7', 'Calling "%s()" with one argument is deprecated, pass the revisions to compare as "from" and "to" arguments, or use "%s::getDiff()" to compare a revision with the working tree.', __METHOD__, WorkingCopy::class); return $this->getLegacyDiff($from); } @@ -546,11 +546,11 @@ public function getSizeInBytes(): int * * @return int A sum, in kilobytes * - * @deprecated since gitonomy/gitlib 2.0, use getSizeInBytes() instead + * @deprecated since gitonomy/gitlib 1.7, use getSizeInBytes() instead */ public function getSize(): int { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "getSizeInBytes()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "getSizeInBytes()" instead.', __METHOD__); return (int) round($this->getSizeInBytes() / 1000); } @@ -561,11 +561,11 @@ public function getSize(): int * @param string $command The command to execute * @param array $env Environment variables of the command * - * @deprecated since gitonomy/gitlib 2.0, run "git shell" with Symfony Process instead + * @deprecated since gitonomy/gitlib 1.7, run "git shell" with Symfony Process instead */ public function shell(string $command, array $env = []): void { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, run "git shell" with Symfony Process instead: it ignores the driver.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, run "git shell" with Symfony Process instead: it ignores the driver.', __METHOD__); $argument = \sprintf('%s %s', $command, escapeshellarg($this->gitDir)); @@ -689,11 +689,11 @@ public function runProcess(string $command, #[\SensitiveParameter] array $args = * * @throws UnsupportedOperationException The driver isn't a CliDriver * - * @deprecated since gitonomy/gitlib 2.0, pass a CliDriver configured with the logger as driver argument instead + * @deprecated since gitonomy/gitlib 1.7, pass a CliDriver configured with the logger as driver argument instead */ public function setLogger(LoggerInterface $logger): static { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, pass a "%s" configured with the logger as driver argument instead.', __METHOD__, CliDriver::class); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, pass a "%s" configured with the logger as driver argument instead.', __METHOD__, CliDriver::class); if (!$this->driver instanceof CliDriver) { throw new UnsupportedOperationException('Only CliDriver logs the git commands it runs.'); @@ -708,11 +708,11 @@ public function setLogger(LoggerInterface $logger): static /** * Returns the logger of the CliDriver. * - * @deprecated since gitonomy/gitlib 2.0, the logger is an argument of CliDriver + * @deprecated since gitonomy/gitlib 1.7, the logger is an argument of CliDriver */ public function getLogger(): ?LoggerInterface { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, the logger is an argument of "%s".', __METHOD__, CliDriver::class); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, the logger is an argument of "%s".', __METHOD__, CliDriver::class); return $this->driver instanceof CliDriver ? $this->driver->getLogger() : null; } @@ -728,11 +728,11 @@ public function getLogger(): ?LoggerInterface * * @return Repository the newly created repository * - * @deprecated since gitonomy/gitlib 2.0, use Repository::cloneBareFrom() or Repository::cloneFrom() with getGitDir() as URL instead + * @deprecated since gitonomy/gitlib 1.7, use Repository::cloneBareFrom() or Repository::cloneFrom() with getGitDir() as URL instead */ public function cloneTo(string $path, bool $bare = true, array $options = []): self { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "%s::%s()" with "getGitDir()" as URL instead.', __METHOD__, self::class, $bare ? 'cloneBareFrom' : 'cloneFrom'); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "%s::%s()" with "getGitDir()" as URL instead.', __METHOD__, self::class, $bare ? 'cloneBareFrom' : 'cloneFrom'); // Like in 1.x, the options configuring git apply to the clone. $options = new LegacyOptions($options); diff --git a/src/Gitonomy/Git/Tree.php b/src/Gitonomy/Git/Tree.php index bef883c4..b36ef119 100644 --- a/src/Gitonomy/Git/Tree.php +++ b/src/Gitonomy/Git/Tree.php @@ -16,9 +16,13 @@ use Gitonomy\Git\Exception\InvalidArgumentException; /** + * Iterating a tree gives its entries, by name. + * * @author Alexandre Salomé + * + * @implements \IteratorAggregate */ -final class Tree +final class Tree implements \IteratorAggregate { /** * @var array|null By name, null until read @@ -40,62 +44,86 @@ public function getHash(): string } /** - * @return array By name + * @return \ArrayIterator The entries, by name */ - public function getEntries(): array + public function getIterator(): \ArrayIterator { - if (null !== $this->entries) { - return $this->entries; - } - - $this->entries = []; - foreach ($this->repository->getRepositoryDriver()->getTreeEntries($this->hash) as $data) { - $object = match ($data->type) { - ObjectType::Blob => $this->repository->getBlob($data->hash), - ObjectType::Tree => $this->repository->getTree($data->hash), - // A commit in a tree is a submodule. - default => new Submodule($data->hash), - }; - $this->entries[$data->name] = new TreeEntry($data->name, $data->mode, $object); - } + return new \ArrayIterator($this->entries()); + } - return $this->entries; + /** + * @return array The blobs, by name + */ + public function getBlobs(): array + { + return array_filter($this->entries(), static fn (TreeEntry $entry): bool => $entry->getObject() instanceof Blob); } /** * @return array The submodules, by name */ - public function getSubmoduleEntries(): array + public function getSubmodules(): array { - return array_filter($this->getEntries(), static fn (TreeEntry $entry): bool => $entry->getObject() instanceof Submodule); + return array_filter($this->entries(), static fn (TreeEntry $entry): bool => $entry->getObject() instanceof Submodule); } /** - * @return array The submodules, by name + * @return array The trees, by name + */ + public function getTrees(): array + { + return array_filter($this->entries(), static fn (TreeEntry $entry): bool => $entry->getObject() instanceof self); + } + + /** + * @return array The mode and the object of each entry, by name * - * @deprecated since gitonomy/gitlib 2.0, use getSubmoduleEntries() instead + * @deprecated since gitonomy/gitlib 1.7, iterate the tree instead */ - public function getCommitReferenceEntries(): array + public function getEntries(): array { - trigger_deprecation('gitonomy/gitlib', '2.0', 'The "%s()" method is deprecated, use "getSubmoduleEntries()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, iterate the tree instead.', __METHOD__); - return $this->getSubmoduleEntries(); + return self::toArrays($this->entries()); } /** - * @return array The trees, by name + * @return array The mode and the blob of each blob, by name + * + * @deprecated since gitonomy/gitlib 1.7, use getBlobs() instead */ - public function getTreeEntries(): array + public function getBlobEntries(): array { - return array_filter($this->getEntries(), static fn (TreeEntry $entry): bool => $entry->getObject() instanceof self); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "getBlobs()" instead.', __METHOD__); + + // @phpstan-ignore return.type (getBlobs() returns blobs only.) + return self::toArrays($this->getBlobs()); } /** - * @return array The blobs, by name + * @return array The mode and the submodule of each submodule, by name + * + * @deprecated since gitonomy/gitlib 1.7, use getSubmodules() instead */ - public function getBlobEntries(): array + public function getCommitReferenceEntries(): array + { + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "getSubmodules()" instead.', __METHOD__); + + // @phpstan-ignore return.type (getSubmodules() returns submodules only.) + return self::toArrays($this->getSubmodules()); + } + + /** + * @return array The mode and the tree of each tree, by name + * + * @deprecated since gitonomy/gitlib 1.7, use getTrees() instead + */ + public function getTreeEntries(): array { - return array_filter($this->getEntries(), static fn (TreeEntry $entry): bool => $entry->getObject() instanceof Blob); + trigger_deprecation('gitonomy/gitlib', '1.7', 'The "%s()" method is deprecated, use "getTrees()" instead.', __METHOD__); + + // @phpstan-ignore return.type (getTrees() returns trees only.) + return self::toArrays($this->getTrees()); } /** @@ -103,7 +131,7 @@ public function getBlobEntries(): array */ public function getEntry(string $name): Submodule|self|Blob { - return ($this->getEntries()[$name] ?? throw new InvalidArgumentException(\sprintf('The tree "%s" has no entry "%s".', $this->hash, $name)))->getObject(); + return ($this->entries()[$name] ?? throw new InvalidArgumentException(\sprintf('The tree "%s" has no entry "%s".', $this->hash, $name)))->getObject(); } /** @@ -121,9 +149,44 @@ public function resolvePath(string $path): Submodule|self|Blob } $resolved[] = $segment; - $element = ($element->getEntries()[$segment] ?? throw new InvalidArgumentException(\sprintf('Unable to resolve "%s": "%s" doesn\'t exist.', $path, implode('/', $resolved))))->getObject(); + $element = ($element->entries()[$segment] ?? throw new InvalidArgumentException(\sprintf('Unable to resolve "%s": "%s" doesn\'t exist.', $path, implode('/', $resolved))))->getObject(); } return $element; } + + /** + * @return array By name + */ + private function entries(): array + { + if (null !== $this->entries) { + return $this->entries; + } + + $this->entries = []; + foreach ($this->repository->getRepositoryDriver()->getTreeEntries($this->hash) as $data) { + $object = match ($data->type) { + ObjectType::Blob => $this->repository->getBlob($data->hash), + ObjectType::Tree => $this->repository->getTree($data->hash), + // A commit in a tree is a submodule. + default => new Submodule($data->hash), + }; + $this->entries[$data->name] = new TreeEntry($data->name, $data->mode, $object); + } + + return $this->entries; + } + + /** + * The entries in the format of 1.x. + * + * @param array $entries + * + * @return array + */ + private static function toArrays(array $entries): array + { + return array_map(static fn (TreeEntry $entry): array => [$entry->getMode(), $entry->getObject()], $entries); + } } diff --git a/src/Gitonomy/Git/TreeEntry.php b/src/Gitonomy/Git/TreeEntry.php index d4dd8daa..a7eab659 100644 --- a/src/Gitonomy/Git/TreeEntry.php +++ b/src/Gitonomy/Git/TreeEntry.php @@ -12,19 +12,12 @@ namespace Gitonomy\Git; -use Gitonomy\Git\Exception\InvalidArgumentException; -use Gitonomy\Git\Exception\LogicException; - /** * An entry of a tree: a blob, a tree or a submodule, with its name and mode. * - * Reading it as an array, [$mode, $object], is deprecated. - * * @author Grégoire Pineau - * - * @implements \ArrayAccess */ -final readonly class TreeEntry implements \ArrayAccess +final readonly class TreeEntry { public function __construct( private string $name, @@ -50,33 +43,4 @@ public function getObject(): Blob|Tree|Submodule { return $this->object; } - - public function offsetExists(mixed $offset): bool - { - return 0 === $offset || 1 === $offset; - } - - /** - * @deprecated since gitonomy/gitlib 2.0, use getMode() and getObject() instead - */ - public function offsetGet(mixed $offset): string|Blob|Tree|Submodule - { - trigger_deprecation('gitonomy/gitlib', '2.0', 'Reading a "%s" as an array is deprecated, use its "getMode()" and "getObject()" methods instead.', self::class); - - return match ($offset) { - 0 => $this->mode, - 1 => $this->object, - default => throw new InvalidArgumentException(\sprintf('A tree entry has no offset %s.', var_export($offset, true))), - }; - } - - public function offsetSet(mixed $offset, mixed $value): void - { - throw new LogicException('A tree entry is immutable.'); - } - - public function offsetUnset(mixed $offset): void - { - throw new LogicException('A tree entry is immutable.'); - } } diff --git a/src/Gitonomy/Git/WorkingCopy.php b/src/Gitonomy/Git/WorkingCopy.php index c2cc2982..fc959417 100644 --- a/src/Gitonomy/Git/WorkingCopy.php +++ b/src/Gitonomy/Git/WorkingCopy.php @@ -83,7 +83,7 @@ public function getDiffStaged(): Diff public function checkout(Revision|string $revision, ?string $branch = null): static { if (null !== $branch) { - trigger_deprecation('gitonomy/gitlib', '2.0', 'Passing a branch to create to "%s()" is deprecated, use "checkoutNewBranch()" instead.', __METHOD__); + trigger_deprecation('gitonomy/gitlib', '1.7', 'Passing a branch to create to "%s()" is deprecated, use "checkoutNewBranch()" instead.', __METHOD__); return $this->checkoutNewBranch($branch, $revision); } diff --git a/tests/Gitonomy/Git/Tests/AdminTest.php b/tests/Gitonomy/Git/Tests/AdminTest.php index d310ab3e..80701707 100644 --- a/tests/Gitonomy/Git/Tests/AdminTest.php +++ b/tests/Gitonomy/Git/Tests/AdminTest.php @@ -30,7 +30,7 @@ class AdminTest extends AbstractTestCase { public function testInit(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Admin::init()" method is deprecated, use "Gitonomy\Git\Repository::initBare()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Admin::init()" method is deprecated, use "Gitonomy\Git\Repository::initBare()" instead.'); $repository = Admin::init(self::createTempDir(), options: self::getOptions()); @@ -39,7 +39,7 @@ public function testInit(): void public function testInitNotBare(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Admin::init()" method is deprecated, use "Gitonomy\Git\Repository::init()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Admin::init()" method is deprecated, use "Gitonomy\Git\Repository::init()" instead.'); $repository = Admin::init(self::createTempDir(), false, self::getOptions()); @@ -48,14 +48,14 @@ public function testInitNotBare(): void public function testIsValidRepository(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Admin::isValidRepository()" method is deprecated, use "Gitonomy\Git\Repository::isValidRepository()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Admin::isValidRepository()" method is deprecated, use "Gitonomy\Git\Repository::isValidRepository()" instead.'); $this->assertTrue(Admin::isValidRepository(self::repositoryUrl(), self::getOptions())); } public function testIsValidRepositoryAndBranch(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Admin::isValidRepositoryAndBranch()" method is deprecated, use "Gitonomy\Git\Repository::isValidRepositoryAndBranch()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Admin::isValidRepositoryAndBranch()" method is deprecated, use "Gitonomy\Git\Repository::isValidRepositoryAndBranch()" instead.'); $this->assertTrue(Admin::isValidRepositoryAndBranch(self::repositoryUrl(), 'new-feature', self::getOptions())); $this->assertFalse(Admin::isValidRepositoryAndBranch(self::repositoryUrl(), 'unknown', self::getOptions())); @@ -63,7 +63,7 @@ public function testIsValidRepositoryAndBranch(): void public function testCloneTo(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Admin::cloneTo()" method is deprecated, use "Gitonomy\Git\Repository::cloneBareFrom()" instead, which takes the URL before the path.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Admin::cloneTo()" method is deprecated, use "Gitonomy\Git\Repository::cloneBareFrom()" instead, which takes the URL before the path.'); $repository = Admin::cloneTo(self::createTempDir(), self::repositoryUrl(), options: self::getOptions()); @@ -73,7 +73,7 @@ public function testCloneTo(): void public function testCloneToNotBare(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Admin::cloneTo()" method is deprecated, use "Gitonomy\Git\Repository::cloneFrom()" instead, which takes the URL before the path.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Admin::cloneTo()" method is deprecated, use "Gitonomy\Git\Repository::cloneFrom()" instead, which takes the URL before the path.'); $repository = Admin::cloneTo(self::createTempDir(), self::repositoryUrl(), false, self::getOptions()); @@ -82,7 +82,7 @@ public function testCloneToNotBare(): void public function testCloneBranchTo(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Admin::cloneBranchTo()" method is deprecated, use "Gitonomy\Git\Repository::cloneBareFrom()" with its "branch" argument instead, which takes the URL before the path.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Admin::cloneBranchTo()" method is deprecated, use "Gitonomy\Git\Repository::cloneBareFrom()" with its "branch" argument instead, which takes the URL before the path.'); $repository = Admin::cloneBranchTo(self::createTempDir(), self::repositoryUrl(), 'new-feature', options: self::getOptions()); @@ -94,7 +94,7 @@ public function testCloneBranchTo(): void public function testCloneBranchToNotBare(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Admin::cloneBranchTo()" method is deprecated, use "Gitonomy\Git\Repository::cloneFrom()" with its "branch" argument instead, which takes the URL before the path.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Admin::cloneBranchTo()" method is deprecated, use "Gitonomy\Git\Repository::cloneFrom()" with its "branch" argument instead, which takes the URL before the path.'); $repository = Admin::cloneBranchTo(self::createTempDir(), self::repositoryUrl(), 'new-feature', false, self::getOptions()); @@ -106,7 +106,7 @@ public function testCloneBranchToNotBare(): void public function testMirrorTo(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Admin::mirrorTo()" method is deprecated, use "Gitonomy\Git\Repository::mirrorFrom()" instead, which takes the URL before the path.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Admin::mirrorTo()" method is deprecated, use "Gitonomy\Git\Repository::mirrorFrom()" instead, which takes the URL before the path.'); $repository = Admin::mirrorTo(self::createTempDir(), self::repositoryUrl(), self::getOptions()); @@ -115,7 +115,7 @@ public function testMirrorTo(): void public function testCloneRepositoryPassesItsArgumentsToGit(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Admin::cloneRepository()" method is deprecated, use "Gitonomy\Git\Repository::cloneFrom()", "Gitonomy\Git\Repository::cloneBareFrom()" or "Gitonomy\Git\Repository::mirrorFrom()" instead, which take the URL before the path; they support no other argument of "git clone".'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Admin::cloneRepository()" method is deprecated, use "Gitonomy\Git\Repository::cloneFrom()", "Gitonomy\Git\Repository::cloneBareFrom()" or "Gitonomy\Git\Repository::mirrorFrom()" instead, which take the URL before the path; they support no other argument of "git clone".'); // --config is the only argument --bare accepts on every git version. $repository = Admin::cloneRepository(self::createTempDir(), self::repositoryUrl(), ['--bare', '--config', 'gitlib.test=yes'], self::getOptions()); @@ -176,7 +176,7 @@ public function testRemovedOptionsAreRefused(): void public function testRepositoryCloneTo(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Repository::cloneTo()" method is deprecated, use "Gitonomy\Git\Repository::cloneBareFrom()" with "getGitDir()" as URL instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Repository::cloneTo()" method is deprecated, use "Gitonomy\Git\Repository::cloneBareFrom()" with "getGitDir()" as URL instead.'); $repository = self::createFoobarRepository(); $new = $repository->cloneTo(self::createTempDir()); @@ -187,7 +187,7 @@ public function testRepositoryCloneTo(): void public function testRepositoryCloneToNotBare(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Repository::cloneTo()" method is deprecated, use "Gitonomy\Git\Repository::cloneFrom()" with "getGitDir()" as URL instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Repository::cloneTo()" method is deprecated, use "Gitonomy\Git\Repository::cloneFrom()" with "getGitDir()" as URL instead.'); $repository = self::createFoobarRepository(); $new = $repository->cloneTo(self::createTempDir(), false); diff --git a/tests/Gitonomy/Git/Tests/BlameTest.php b/tests/Gitonomy/Git/Tests/BlameTest.php index f05fe4ed..9d71544e 100644 --- a/tests/Gitonomy/Git/Tests/BlameTest.php +++ b/tests/Gitonomy/Git/Tests/BlameTest.php @@ -154,7 +154,7 @@ public function testBlameOfAPathNormalizesIt(): void #[IgnoreDeprecations] public function testLegacyBlameLineRange(bool $bare): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: Passing a range of lines as a string to "Gitonomy\Git\Repository::getBlame()" is deprecated, pass the first and the last lines instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: Passing a range of lines as a string to "Gitonomy\Git\Repository::getBlame()" is deprecated, pass the first and the last lines instead.'); $repository = self::createFoobarRepository($bare); diff --git a/tests/Gitonomy/Git/Tests/BlobTest.php b/tests/Gitonomy/Git/Tests/BlobTest.php index 8f5c214b..c6066389 100644 --- a/tests/Gitonomy/Git/Tests/BlobTest.php +++ b/tests/Gitonomy/Git/Tests/BlobTest.php @@ -39,7 +39,7 @@ public function testGetContentSiblingToSubmodule(bool $bare): void // making sibling blobs unreadable. $tree = $repository->getCommit(self::NO_MESSAGE_COMMIT)->getTree(); - $this->assertNotEmpty($tree->getSubmoduleEntries(), 'Tree contains a submodule entry'); + $this->assertNotEmpty($tree->getSubmodules(), 'Tree contains a submodule entry'); $blob = $tree->resolvePath('README.md'); diff --git a/tests/Gitonomy/Git/Tests/CommitTest.php b/tests/Gitonomy/Git/Tests/CommitTest.php index a3dba6e3..e0174d98 100644 --- a/tests/Gitonomy/Git/Tests/CommitTest.php +++ b/tests/Gitonomy/Git/Tests/CommitTest.php @@ -325,7 +325,7 @@ public function testGetSignedMessage(bool $bare): void #[IgnoreDeprecations] public function testLegacyGetFixedShortHash(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Commit::getFixedShortHash()" method is deprecated, use "substr($commit->getHash(), 0, $length)" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Commit::getFixedShortHash()" method is deprecated, use "substr($commit->getHash(), 0, $length)" instead.'); $this->assertSame(substr(self::LONGFILE_COMMIT, 0, 6), self::createFoobarRepository()->getCommit(self::LONGFILE_COMMIT)->getFixedShortHash()); } @@ -335,7 +335,7 @@ public function testLegacyGetFixedShortHash(): void #[IgnoreDeprecations] public function testGetShortMessage(bool $bare): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Commit::getShortMessage()" method is deprecated, use symfony/string instead: "u($commit->getSubjectMessage())->truncate($length, $separator, !$preserve)".'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Commit::getShortMessage()" method is deprecated, use symfony/string instead: "u($commit->getSubjectMessage())->truncate($length, $separator, !$preserve)".'); $repository = self::createFoobarRepository($bare); // tests with a multi-line message @@ -414,7 +414,7 @@ public function testGetIncludingBranches(bool $bare): void #[IgnoreDeprecations] public function testLegacyGetIncludingLocalOrRemoteBranches(bool $bare): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: Passing arguments to "Gitonomy\Git\Commit::getIncludingBranches()" is deprecated, filter the branches it returns with "Gitonomy\Git\Reference\Branch::isLocal()" or "isRemote()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: Passing arguments to "Gitonomy\Git\Commit::getIncludingBranches()" is deprecated, filter the branches it returns with "Gitonomy\Git\Reference\Branch::isLocal()" or "isRemote()" instead.'); $repository = self::createFoobarRepository($bare); $commit = $repository->getCommit(self::INITIAL_COMMIT); diff --git a/tests/Gitonomy/Git/Tests/DiffTest.php b/tests/Gitonomy/Git/Tests/DiffTest.php index 4ce9a8a3..5cb585f6 100644 --- a/tests/Gitonomy/Git/Tests/DiffTest.php +++ b/tests/Gitonomy/Git/Tests/DiffTest.php @@ -395,7 +395,7 @@ public function testDiffsOfAConflictLeaveUnmergedPathsOut(): void // Like git diff HEAD, which compares the unmerged file, conflict markers included, to HEAD. $files = $repository->getWorkingCopy()->getDiff()->getFiles(); $this->assertSame(['conflict', 'other'], array_map(static fn (File $file): string => $file->getName(), $files)); - $this->assertContains('<<<<<<< HEAD', array_map(static fn (DiffLine $line): string => $line->getContent(), $files[0]->getChanges()[0]->getLines())); + $this->assertContains('<<<<<<< HEAD', array_map(static fn (DiffLine $line): string => $line->getContent(), $files[0]->getChanges()[0]->getDiffLines())); } public function testWorkingCopyDiff(): void @@ -408,8 +408,8 @@ public function testWorkingCopyDiff(): void $this->assertCount(1, $files); $this->assertSame(1, $files[0]->getAdditions()); - $this->assertSame([DiffLineType::Context, DiffLineType::Addition], array_map(static fn (DiffLine $line): DiffLineType => $line->getType(), $files[0]->getChanges()[0]->getLines())); - $this->assertSame('b', $files[0]->getChanges()[0]->getLines()[1]->getContent()); + $this->assertSame([DiffLineType::Context, DiffLineType::Addition], array_map(static fn (DiffLine $line): DiffLineType => $line->getType(), $files[0]->getChanges()[0]->getDiffLines())); + $this->assertSame('b', $files[0]->getChanges()[0]->getDiffLines()[1]->getContent()); } public function testHunkWithOneLine(): void @@ -442,7 +442,7 @@ public function testParseQuotedNames(): void #[IgnoreDeprecations] public function testLegacyGetDiffOfARange(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: Calling "Gitonomy\Git\Repository::getDiff()" with one argument is deprecated, pass the revisions to compare as "from" and "to" arguments, or use "Gitonomy\Git\WorkingCopy::getDiff()" to compare a revision with the working tree.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: Calling "Gitonomy\Git\Repository::getDiff()" with one argument is deprecated, pass the revisions to compare as "from" and "to" arguments, or use "Gitonomy\Git\WorkingCopy::getDiff()" to compare a revision with the working tree.'); $repository = self::createFoobarRepository(); @@ -452,20 +452,42 @@ public function testLegacyGetDiffOfARange(): void #[Group('legacy')] #[IgnoreDeprecations] - public function testLegacyLinesAsArrays(): void + public function testLegacyGetLines(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: Reading a "Gitonomy\Git\Diff\DiffLine" as an array is deprecated, use its "getType()" and "getContent()" methods instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Diff\FileChange::getLines()" method is deprecated, use "getDiffLines()" instead.'); - $line = new DiffLine(DiffLineType::Addition, 'added'); - [$type, $content] = $line; + $change = new FileChange(1, 1, 1, 2, [new DiffLine(DiffLineType::Context, 'kept'), new DiffLine(DiffLineType::Addition, 'added')]); + + $this->assertSame([[FileChange::LINE_CONTEXT, 'kept'], [FileChange::LINE_ADD, 'added']], $change->getLines()); + } + + #[Group('legacy')] + #[IgnoreDeprecations] + public function testLegacyConstructorWithLinesAsArrays(): void + { + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: Passing the lines to "Gitonomy\Git\Diff\FileChange::__construct()" as arrays is deprecated, pass "Gitonomy\Git\Diff\DiffLine" objects instead.'); + + $change = new FileChange(1, 1, 1, 2, [[FileChange::LINE_CONTEXT, 'kept'], new DiffLine(DiffLineType::Addition, 'added')]); + + $this->assertSame([[DiffLineType::Context, 'kept'], [DiffLineType::Addition, 'added']], array_map(static fn (DiffLine $line): array => [$line->getType(), $line->getContent()], $change->getDiffLines())); + $this->assertSame(1, $change->getAdditions()); + } + + #[Group('legacy')] + #[IgnoreDeprecations] + public function testLegacyConstructorRefusesAnUnknownTypeOfLine(): void + { + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: Passing the lines to "Gitonomy\Git\Diff\FileChange::__construct()" as arrays is deprecated, pass "Gitonomy\Git\Diff\DiffLine" objects instead.'); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Unknown type of line 2: the types are 1 (an addition), 0 (a context line) and -1 (a deletion).'); - $this->assertSame([FileChange::LINE_ADD, 'added'], [$type, $content]); + new FileChange(1, 1, 1, 1, [[2, 'line']]); } public function testFromArrayRefusesAnUnknownTypeOfLine(): void { $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Unknown type of line 2: the types are FileChange::LINE_ADD, LINE_CONTEXT and LINE_REMOVE.'); + $this->expectExceptionMessage('Unknown type of line 2: the types are 1 (an addition), 0 (a context line) and -1 (a deletion).'); FileChange::fromArray(['range_old_start' => 1, 'range_old_count' => 1, 'range_new_start' => 1, 'range_new_count' => 1, 'lines' => [[2, 'line']]]); } @@ -506,7 +528,7 @@ public function testGetBlobWithoutRepositoryThrows(): void #[IgnoreDeprecations] public function testLegacySetRepository(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Diff\File::setRepository()" method is deprecated, the diffs gitlib returns have their repository already.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Diff\File::setRepository()" method is deprecated, the diffs gitlib returns have their repository already.'); $repository = self::createFoobarRepository(); $file = new File('README.md', 'README.md', '100644', '100644', null, null, false); @@ -519,7 +541,7 @@ public function testLegacySetRepository(): void #[IgnoreDeprecations] public function testLegacyDiffSetRepository(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Diff\Diff::setRepository()" method is deprecated, the diffs gitlib returns have their repository already.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Diff\Diff::setRepository()" method is deprecated, the diffs gitlib returns have their repository already.'); $repository = self::createFoobarRepository(); $diff = Diff::parse(":100644 100644 1111111111111111111111111111111111111111 2222222222222222222222222222222222222222 M\tREADME.md\n"); @@ -532,7 +554,7 @@ public function testLegacyDiffSetRepository(): void #[IgnoreDeprecations] public function testLegacyAddChange(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Diff\File::addChange()" method is deprecated, give the changes to the constructor instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Diff\File::addChange()" method is deprecated, give the changes to the constructor instead.'); $file = new File('README.md', 'README.md', '100644', '100644', null, null, false); $change = new FileChange(1, 1, 1, 1, [new DiffLine(DiffLineType::Addition, 'added')]); @@ -545,7 +567,7 @@ public function testLegacyAddChange(): void #[IgnoreDeprecations] public function testLegacyIsChangeMode(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Diff\File::isChangeMode()" method is deprecated, use "isModeChange()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Diff\File::isChangeMode()" method is deprecated, use "isModeChange()" instead.'); $this->assertTrue(new File('run.sh', 'run.sh', '100644', '100755', null, null, false)->isChangeMode()); } @@ -554,7 +576,7 @@ public function testLegacyIsChangeMode(): void #[IgnoreDeprecations] public function testLegacyFileIsDelete(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Diff\File::isDelete()" method is deprecated, use "isDeletion()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Diff\File::isDelete()" method is deprecated, use "isDeletion()" instead.'); $this->assertTrue(new File('README.md', null, '100644', null, null, null, false)->isDelete()); } @@ -563,7 +585,7 @@ public function testLegacyFileIsDelete(): void #[IgnoreDeprecations] public function testLegacyGetAnchor(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Diff\File::getAnchor()" method is deprecated, use "substr($file->getNewIndex(), 0, 12)" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Diff\File::getAnchor()" method is deprecated, use "substr($file->getNewIndex(), 0, 12)" instead.'); $this->assertSame('222222222222', new File('README.md', 'README.md', '100644', '100644', str_repeat('1', 40), str_repeat('2', 40), false)->getAnchor()); } @@ -572,7 +594,7 @@ public function testLegacyGetAnchor(): void #[IgnoreDeprecations] public function testLegacyGetCount(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Diff\FileChange::getCount()" method is deprecated, use "getAdditions()" or "getDeletions()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Diff\FileChange::getCount()" method is deprecated, use "getAdditions()" or "getDeletions()" instead.'); $change = new FileChange(1, 1, 1, 2, [new DiffLine(DiffLineType::Context, 'kept'), new DiffLine(DiffLineType::Addition, 'added')]); @@ -766,7 +788,7 @@ private static function changes(Diff $diff): array $change->getRangeOldCount(), $change->getRangeNewStart(), $change->getRangeNewCount(), - array_map(static fn (DiffLine $line): array => [$line->getType()->name, $line->getContent()], $change->getLines()), + array_map(static fn (DiffLine $line): array => [$line->getType()->name, $line->getContent()], $change->getDiffLines()), ], $file->getChanges())], $diff->getFiles()); } diff --git a/tests/Gitonomy/Git/Tests/LogTest.php b/tests/Gitonomy/Git/Tests/LogTest.php index ebca07c0..045bd33b 100644 --- a/tests/Gitonomy/Git/Tests/LogTest.php +++ b/tests/Gitonomy/Git/Tests/LogTest.php @@ -339,7 +339,7 @@ public function testWithersReturnAnotherLog(bool $bare): void #[IgnoreDeprecations] public function testLegacySetOffset(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Log::setOffset()" method is deprecated, use "withOffset()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Log::setOffset()" method is deprecated, use "withOffset()" instead.'); $log = self::createFoobarRepository()->getLog(); $log->setOffset(2); @@ -351,7 +351,7 @@ public function testLegacySetOffset(): void #[IgnoreDeprecations] public function testLegacySetLimit(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Log::setLimit()" method is deprecated, use "withLimit()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Log::setLimit()" method is deprecated, use "withLimit()" instead.'); $log = self::createFoobarRepository()->getLog(self::LONGFILE_COMMIT); @@ -363,7 +363,7 @@ public function testLegacySetLimit(): void #[IgnoreDeprecations] public function testLegacyGetDiffIgnoresThePathsOfTheLog(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Log::getDiff()" method is deprecated, use "Gitonomy\Git\Repository::getDiff()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Log::getDiff()" method is deprecated, use "Gitonomy\Git\Repository::getDiff()" instead.'); $repository = self::createFoobarRepository(); $diff = $repository->getDiff(self::BEFORE_LONGFILE_COMMIT, self::LONGFILE_COMMIT)->toArray(); diff --git a/tests/Gitonomy/Git/Tests/PushReferenceTest.php b/tests/Gitonomy/Git/Tests/PushReferenceTest.php index 191bbfc8..6092b15c 100644 --- a/tests/Gitonomy/Git/Tests/PushReferenceTest.php +++ b/tests/Gitonomy/Git/Tests/PushReferenceTest.php @@ -53,7 +53,7 @@ public static function provideIsers(): array #[IgnoreDeprecations] public function testLegacyIsCreate(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\PushReference::isCreate()" method is deprecated, use "isCreation()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\PushReference::isCreate()" method is deprecated, use "isCreation()" instead.'); $this->assertTrue(new PushReference(self::createFoobarRepository(), 'foo', PushReference::ZERO, self::LONGFILE_COMMIT)->isCreate()); } @@ -62,7 +62,7 @@ public function testLegacyIsCreate(): void #[IgnoreDeprecations] public function testLegacyIsDelete(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\PushReference::isDelete()" method is deprecated, use "isDeletion()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\PushReference::isDelete()" method is deprecated, use "isDeletion()" instead.'); $this->assertTrue(new PushReference(self::createFoobarRepository(), 'foo', self::LONGFILE_COMMIT, PushReference::ZERO)->isDelete()); } @@ -71,7 +71,7 @@ public function testLegacyIsDelete(): void #[IgnoreDeprecations] public function testLegacyGetReference(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\PushReference::getReference()" method is deprecated, use "getFullname()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\PushReference::getReference()" method is deprecated, use "getFullname()" instead.'); $this->assertSame('refs/heads/foo', new PushReference(self::createFoobarRepository(), 'refs/heads/foo', self::BEFORE_LONGFILE_COMMIT, self::LONGFILE_COMMIT)->getReference()); } @@ -80,7 +80,7 @@ public function testLegacyGetReference(): void #[IgnoreDeprecations] public function testLegacyGetRevision(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\PushReference::getRevision()" method is deprecated, use "getRange()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\PushReference::getRevision()" method is deprecated, use "getRange()" instead.'); $this->assertSame(self::BEFORE_LONGFILE_COMMIT.'..'.self::LONGFILE_COMMIT, new PushReference(self::createFoobarRepository(), 'refs/heads/foo', self::BEFORE_LONGFILE_COMMIT, self::LONGFILE_COMMIT)->getRevision()); } diff --git a/tests/Gitonomy/Git/Tests/ReferenceTest.php b/tests/Gitonomy/Git/Tests/ReferenceTest.php index b944031a..d17fc808 100644 --- a/tests/Gitonomy/Git/Tests/ReferenceTest.php +++ b/tests/Gitonomy/Git/Tests/ReferenceTest.php @@ -21,6 +21,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; +use Symfony\Component\Process\Process; class ReferenceTest extends AbstractTestCase { @@ -283,7 +284,7 @@ public function testIsBranchMergedToMaster(): void #[IgnoreDeprecations] public function testLegacyIsMergedTo(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Reference\Branch::isMergedTo()" method is deprecated, use "Gitonomy\Git\Reference\Branch::isMergedInto()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Reference\Branch::isMergedTo()" method is deprecated, use "Gitonomy\Git\Reference\Branch::isMergedInto()" instead.'); $repository = self::createFoobarRepository(false); $references = $repository->getReferences(); @@ -344,7 +345,7 @@ public function testBranchMoveTo(): void #[IgnoreDeprecations] public function testLegacyUpdate(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\ReferenceBag::update()" method is deprecated, use "Gitonomy\Git\Reference\Branch::moveTo()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\ReferenceBag::update()" method is deprecated, use "Gitonomy\Git\Reference\Branch::moveTo()" instead.'); $repository = self::createFoobarRepository(); $references = $repository->getReferences(); @@ -354,6 +355,19 @@ public function testLegacyUpdate(): void $this->assertSame(self::INITIAL_COMMIT, $references->getBranch('master')->getCommitHash()); } + #[Group('legacy')] + #[IgnoreDeprecations] + public function testLegacyGetReferencesReadsThemAgain(): void + { + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: Passing an argument to "Gitonomy\Git\Repository::getReferences()" is deprecated, gitlib reads the references again after its writes: open a new Repository to see the writes of other processes.'); + + $repository = self::createFoobarRepository(); + $this->assertFalse($repository->getReferences()->hasBranch('elsewhere')); + new Process([self::gitCommand(), 'branch', 'elsewhere', 'master'], $repository->getGitDir(), self::gitEnvs())->mustRun(); + + $this->assertTrue($repository->getReferences(true)->hasBranch('elsewhere')); + } + public function testBranchesEndingWithHead(): void { $repository = self::createFoobarRepository(); diff --git a/tests/Gitonomy/Git/Tests/RepositoryTest.php b/tests/Gitonomy/Git/Tests/RepositoryTest.php index 7a907b17..236c4b74 100644 --- a/tests/Gitonomy/Git/Tests/RepositoryTest.php +++ b/tests/Gitonomy/Git/Tests/RepositoryTest.php @@ -480,7 +480,7 @@ public function testAnObjectOfAnotherTypeThrows(): void foreach ([ 'blob' => static fn () => $repository->getBlob(self::LONGFILE_COMMIT)->getContent(), - 'tree' => static fn () => $repository->getTree(self::LONGFILE_COMMIT)->getEntries(), + 'tree' => static fn () => iterator_to_array($repository->getTree(self::LONGFILE_COMMIT)), 'commit' => static fn () => $repository->getCommit($treeHash)->getMessage(), ] as $type => $read) { try { @@ -825,7 +825,7 @@ public function testGetSizeInBytesOfAnUnreadableDirectoryThrows(): void #[IgnoreDeprecations] public function testLegacyGetSizeInKilobytes(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Repository::getSize()" method is deprecated, use "getSizeInBytes()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Repository::getSize()" method is deprecated, use "getSizeInBytes()" instead.'); $repository = self::createFoobarRepository(); @@ -955,7 +955,7 @@ public function testDriverOpensTheRepository(): void #[IgnoreDeprecations] public function testLegacySetLogger(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Repository::setLogger()" method is deprecated, pass a "Gitonomy\Git\Driver\Cli\CliDriver" configured with the logger as driver argument instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Repository::setLogger()" method is deprecated, pass a "Gitonomy\Git\Driver\Cli\CliDriver" configured with the logger as driver argument instead.'); $logger = $this->createMock(LoggerInterface::class); $logger->expects($this->once()) @@ -987,7 +987,7 @@ public function testLegacyShell(): void $this->markTestSkipped('The command of git shell is a shell script.'); } - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Repository::shell()" method is deprecated, run "git shell" with Symfony Process instead: it ignores the driver.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Repository::shell()" method is deprecated, run "git shell" with Symfony Process instead: it ignores the driver.'); // git shell runs the commands of ~/git-shell-commands. $home = self::createTempDir(); @@ -1029,7 +1029,7 @@ public function testUnknownOptionsAreRefused(): void #[IgnoreDeprecations] public function testLegacyOptionsConfigureACliDriver(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: Passing an array of options to "Gitonomy\Git\Repository::__construct()" is deprecated, pass the working directory as "workingDir" argument, and configure the logger and git through the "driver" argument.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: Passing an array of options to "Gitonomy\Git\Repository::__construct()" is deprecated, pass the working directory as "workingDir" argument, and configure the logger and git through the "driver" argument.'); $logger = $this->createStub(LoggerInterface::class); $repository = new Repository(self::createFoobarRepository()->getGitDir(), [ @@ -1056,7 +1056,7 @@ public function testLegacyOptionsCantBeCombinedWithADriver(): void #[IgnoreDeprecations] public function testLegacyDebugOption(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: Passing an array of options to "Gitonomy\Git\Repository::__construct()" is deprecated, pass the working directory as "workingDir" argument, and configure the logger and git through the "driver" argument.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: Passing an array of options to "Gitonomy\Git\Repository::__construct()" is deprecated, pass the working directory as "workingDir" argument, and configure the logger and git through the "driver" argument.'); $repository = new Repository(self::createFoobarRepository()->getGitDir(), ['debug' => true], self::getDriver()); diff --git a/tests/Gitonomy/Git/Tests/TreeTest.php b/tests/Gitonomy/Git/Tests/TreeTest.php index e702aaff..2e64b54b 100644 --- a/tests/Gitonomy/Git/Tests/TreeTest.php +++ b/tests/Gitonomy/Git/Tests/TreeTest.php @@ -27,12 +27,12 @@ class TreeTest extends AbstractTestCase public const PATH_RESOLVING_COMMIT = 'cc06ac171d884282202dff88c1ded499a1f89420'; #[DataProvider('provideBare')] - public function testGetEntries(bool $bare): void + public function testIterate(bool $bare): void { $repository = self::createFoobarRepository($bare); $tree = $repository->getCommit(self::LONGFILE_COMMIT)->getTree(); - $entries = $tree->getEntries(); + $entries = iterator_to_array($tree); $this->assertInstanceOf(Blob::class, $entries['long.php']->getObject()); $this->assertSame('long.php', $entries['long.php']->getName()); @@ -41,15 +41,15 @@ public function testGetEntries(bool $bare): void } #[DataProvider('provideBare')] - public function testGetEntriesWithNonAsciiNames(bool $bare): void + public function testIterateWithNonAsciiNames(bool $bare): void { $repository = self::createFoobarRepository($bare); - $entries = $repository->getCommit(DiffTest::FILE_WITH_UMLAUTS_COMMIT)->getTree()->getEntries(); + $entries = iterator_to_array($repository->getCommit(DiffTest::FILE_WITH_UMLAUTS_COMMIT)->getTree()); $this->assertArrayHasKey('file_with_umlauts_äöü', $entries); } - public function testGetEntriesWithSpecialCharactersInNames(): void + public function testIterateWithSpecialCharactersInNames(): void { $repository = self::createFoobarRepository(false); self::git($repository, 'config', ['user.name', 'Unit Test']); @@ -58,18 +58,18 @@ public function testGetEntriesWithSpecialCharactersInNames(): void self::git($repository, 'add', ['--all']); self::git($repository, 'commit', ['-m', 'Add a file with special characters in its name']); - $entries = $repository->getHeadCommit()->getTree()->getEntries(); + $entries = iterator_to_array($repository->getHeadCommit()->getTree()); $this->assertArrayHasKey('back\slash'."\ttab\"quote", $entries); } #[DataProvider('provideBare')] - public function testGetSubmoduleEntries(bool $bare): void + public function testGetSubmodules(bool $bare): void { $repository = self::createFoobarRepository($bare); $tree = $repository->getCommit(self::NO_MESSAGE_COMMIT)->getTree(); - $submodules = $tree->getSubmoduleEntries(); + $submodules = $tree->getSubmodules(); $this->assertSame(['barbaz'], array_keys($submodules)); $this->assertInstanceOf(Submodule::class, $submodules['barbaz']->getObject()); @@ -85,7 +85,7 @@ public function testGetSubmoduleEntries(bool $bare): void #[RunInSeparateProcess] public function testLegacyCommitReference(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\CommitReference" class is deprecated, use "Gitonomy\Git\Submodule" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\CommitReference" class is deprecated, use "Gitonomy\Git\Submodule" instead.'); $this->assertTrue(class_exists(CommitReference::class)); } @@ -95,8 +95,7 @@ public function testLegacyCommitReference(): void #[IgnoreDeprecations] public function testLegacyGetCommitReferenceEntries(bool $bare): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: The "Gitonomy\Git\Tree::getCommitReferenceEntries()" method is deprecated, use "getSubmoduleEntries()" instead.'); - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: Reading a "Gitonomy\Git\TreeEntry" as an array is deprecated, use its "getMode()" and "getObject()" methods instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Tree::getCommitReferenceEntries()" method is deprecated, use "getSubmodules()" instead.'); $tree = self::createFoobarRepository($bare)->getCommit(self::NO_MESSAGE_COMMIT)->getTree(); @@ -136,27 +135,71 @@ public function testResolveTheRootPath(): void } #[DataProvider('provideBare')] - public function testGetTreeEntries(bool $bare): void + public function testGetTrees(bool $bare): void { $repository = self::createFoobarRepository($bare); - $tree = $repository->getCommit(self::NO_MESSAGE_COMMIT)->getTree(); - $trees = $tree->getTreeEntries(); + $this->assertSame([], $repository->getCommit(self::NO_MESSAGE_COMMIT)->getTree()->getTrees()); - $this->assertEmpty($trees); + $trees = $repository->getCommit(self::PATH_RESOLVING_COMMIT)->getTree()->getTrees(); + + $this->assertSame(['test'], array_keys($trees)); + $this->assertInstanceOf(Tree::class, $trees['test']->getObject()); + $this->assertSame('040000', $trees['test']->getMode()); } #[DataProvider('provideBare')] - public function testGetBlobEntries(bool $bare): void + public function testGetBlobs(bool $bare): void { $repository = self::createFoobarRepository($bare); $tree = $repository->getCommit(self::NO_MESSAGE_COMMIT)->getTree(); - $blobs = $tree->getBlobEntries(); + $blobs = $tree->getBlobs(); + $this->assertArrayNotHasKey('barbaz', $blobs); $this->assertInstanceOf(Blob::class, $blobs['README.md']->getObject()); } + #[Group('legacy')] + #[IgnoreDeprecations] + public function testLegacyGetEntries(): void + { + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Tree::getEntries()" method is deprecated, iterate the tree instead.'); + + $tree = self::createFoobarRepository()->getCommit(self::NO_MESSAGE_COMMIT)->getTree(); + + $entries = $tree->getEntries(); + + $this->assertSame(array_keys(iterator_to_array($tree)), array_keys($entries)); + $this->assertSame(['100644', $tree->getEntry('README.md')], $entries['README.md']); + $this->assertSame(['160000', $tree->getEntry('barbaz')], $entries['barbaz']); + } + + #[Group('legacy')] + #[IgnoreDeprecations] + public function testLegacyGetBlobEntries(): void + { + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Tree::getBlobEntries()" method is deprecated, use "getBlobs()" instead.'); + + $tree = self::createFoobarRepository()->getCommit(self::NO_MESSAGE_COMMIT)->getTree(); + + $blobs = $tree->getBlobEntries(); + + $this->assertSame(array_keys($tree->getBlobs()), array_keys($blobs)); + $this->assertSame(['100644', $tree->getEntry('README.md')], $blobs['README.md']); + } + + #[Group('legacy')] + #[IgnoreDeprecations] + public function testLegacyGetTreeEntries(): void + { + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: The "Gitonomy\Git\Tree::getTreeEntries()" method is deprecated, use "getTrees()" instead.'); + + $tree = self::createFoobarRepository()->getCommit(self::PATH_RESOLVING_COMMIT)->getTree(); + + $this->assertSame(['test' => ['040000', $tree->getEntry('test')]], $tree->getTreeEntries()); + } + #[DataProvider('provideBare')] public function testResolvePath(bool $bare): void { @@ -166,7 +209,7 @@ public function testResolvePath(bool $bare): void $resolved = $tree->resolvePath($path); $this->assertInstanceOf(Tree::class, $resolved); - $entries = $resolved->getEntries(); + $entries = iterator_to_array($resolved); $this->assertArrayHasKey('d', $entries, 'Successfully resolved source folder'); } diff --git a/tests/Gitonomy/Git/Tests/WorkingCopyTest.php b/tests/Gitonomy/Git/Tests/WorkingCopyTest.php index 0b756c06..f5d52c04 100644 --- a/tests/Gitonomy/Git/Tests/WorkingCopyTest.php +++ b/tests/Gitonomy/Git/Tests/WorkingCopyTest.php @@ -65,7 +65,7 @@ public function testCheckoutOfABranchObjectAttachesHead(): void #[IgnoreDeprecations] public function testLegacyCheckoutOfANewBranch(): void { - $this->expectUserDeprecationMessage('Since gitonomy/gitlib 2.0: Passing a branch to create to "Gitonomy\Git\WorkingCopy::checkout()" is deprecated, use "checkoutNewBranch()" instead.'); + $this->expectUserDeprecationMessage('Since gitonomy/gitlib 1.7: Passing a branch to create to "Gitonomy\Git\WorkingCopy::checkout()" is deprecated, use "checkoutNewBranch()" instead.'); $repository = self::createFoobarRepository(false); $repository->getWorkingCopy()->checkout('origin/new-feature', 'new-feature');