From 91e4259af1aade34e4951de13f75c06f1e066c47 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sat, 15 Nov 2025 14:02:23 +0100 Subject: [PATCH 1/9] require php 8.4 --- .github/workflows/ci.yml | 10 ++++------ CHANGELOG.md | 6 ++++++ composer.json | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 189105d..779f162 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,13 +4,11 @@ on: [push, pull_request] jobs: blackbox: - uses: innmind/github-workflows/.github/workflows/black-box-matrix.yml@main + uses: innmind/github-workflows/.github/workflows/black-box-matrix.yml@next coverage: - uses: innmind/github-workflows/.github/workflows/coverage-matrix.yml@main + uses: innmind/github-workflows/.github/workflows/coverage-matrix.yml@next secrets: inherit psalm: - uses: innmind/github-workflows/.github/workflows/psalm-matrix.yml@main + uses: innmind/github-workflows/.github/workflows/psalm-matrix.yml@next cs: - uses: innmind/github-workflows/.github/workflows/cs.yml@main - with: - php-version: '8.2' + uses: innmind/github-workflows/.github/workflows/cs.yml@next diff --git a/CHANGELOG.md b/CHANGELOG.md index dd66d4e..32a76ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Unreleased] + +### Changed + +- Requires PHP `8.4` + ## 2.0.0 - 2025-04-16 ### Changed diff --git a/composer.json b/composer.json index 7f0e3da..61d60aa 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "issues": "http://github.com/innmind/encoding/issues" }, "require": { - "php": "~8.2", + "php": "~8.4", "innmind/immutable": "~5.7", "innmind/filesystem": "~8.0", "innmind/time-continuum": "~4.1" From d56c6fbc359d1e5e7c62abf6ad3dce055026a780 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sat, 15 Nov 2025 14:05:09 +0100 Subject: [PATCH 2/9] update dependencies --- composer.json | 11 ++++++++--- proofs/tar.php | 16 ++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index 61d60aa..b597ffd 100644 --- a/composer.json +++ b/composer.json @@ -16,9 +16,14 @@ }, "require": { "php": "~8.4", - "innmind/immutable": "~5.7", - "innmind/filesystem": "~8.0", - "innmind/time-continuum": "~4.1" + "innmind/immutable": "dev-next", + "innmind/filesystem": "dev-next", + "innmind/time-continuum": "dev-next", + "innmind/io": "dev-next", + "innmind/media-type": "dev-next", + "innmind/url": "dev-next", + "innmind/validation": "dev-next", + "innmind/ip": "dev-next" }, "autoload": { "psr-4": { diff --git a/proofs/tar.php b/proofs/tar.php index 00ecf9c..37c4ac8 100644 --- a/proofs/tar.php +++ b/proofs/tar.php @@ -3,7 +3,7 @@ use Innmind\Encoding\Tar; use Innmind\Filesystem\{ - Adapter\Filesystem, + Adapter, Name, File, Directory, @@ -27,8 +27,8 @@ static function($assert, $name) { $clock = Clock::live(); $path = \rtrim(\sys_get_temp_dir(), '/').'/innmind/encoding/'; - $tmp = Filesystem::mount(Path::of($path)); - $adapter = Filesystem::mount(Path::of('fixtures/')); + $tmp = Adapter::mount(Path::of($path))->unwrap(); + $adapter = Adapter::mount(Path::of('fixtures/'))->unwrap(); $tar = $adapter ->get(Name::of($name)) ->map(static fn($file) => $file->rename(Name::of('other-'.$name))) @@ -67,8 +67,8 @@ static function($assert, $name) { static function($assert) { $clock = Clock::live(); $path = \rtrim(\sys_get_temp_dir(), '/').'/innmind/encoding/'; - $tmp = Filesystem::mount(Path::of($path)); - $adapter = Filesystem::mount(Path::of('./')); + $tmp = Adapter::mount(Path::of($path))->unwrap(); + $adapter = Adapter::mount(Path::of('./'))->unwrap(); $tar = $adapter ->get(Name::of('fixtures')) ->map(Tar::encode($clock)) @@ -142,8 +142,8 @@ static function($assert, $name1, $name2) { $clock = Clock::live(); $path = \rtrim(\sys_get_temp_dir(), '/').'/innmind/encoding/'; - $tmp = Filesystem::mount(Path::of($path)); - $adapter = Filesystem::mount(Path::of('./')); + $tmp = Adapter::mount(Path::of($path))->unwrap(); + $adapter = Adapter::mount(Path::of('./'))->unwrap(); $tar = $adapter ->get(Name::of('fixtures')) ->map(Directory::of($name2)->add(...)) @@ -221,7 +221,7 @@ static function($assert, $name1, $name2) { static function($assert, $file) { $clock = Clock::live(); $path = \rtrim(\sys_get_temp_dir(), '/').'/innmind/encoding/'; - $tmp = Filesystem::mount(Path::of($path)); + $tmp = Adapter::mount(Path::of($path))->unwrap(); // make sure to avoid conflicts when trying to unarchive $tmp->remove($file->name()); From 09b4a4e5a00a4b7dc53d2c956420b7abe973ec48 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sun, 1 Feb 2026 17:42:44 +0100 Subject: [PATCH 3/9] tag dependencies --- .github/workflows/ci.yml | 8 ++++---- composer.json | 13 ++++--------- proofs/gzip.php | 8 ++++---- proofs/tar.php | 29 ++++++++++++++++++++++------- 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 779f162..2f3eecb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,11 +4,11 @@ on: [push, pull_request] jobs: blackbox: - uses: innmind/github-workflows/.github/workflows/black-box-matrix.yml@next + uses: innmind/github-workflows/.github/workflows/black-box-matrix.yml@main coverage: - uses: innmind/github-workflows/.github/workflows/coverage-matrix.yml@next + uses: innmind/github-workflows/.github/workflows/coverage-matrix.yml@main secrets: inherit psalm: - uses: innmind/github-workflows/.github/workflows/psalm-matrix.yml@next + uses: innmind/github-workflows/.github/workflows/psalm-matrix.yml@main cs: - uses: innmind/github-workflows/.github/workflows/cs.yml@next + uses: innmind/github-workflows/.github/workflows/cs.yml@main diff --git a/composer.json b/composer.json index b597ffd..6d0befe 100644 --- a/composer.json +++ b/composer.json @@ -16,14 +16,9 @@ }, "require": { "php": "~8.4", - "innmind/immutable": "dev-next", - "innmind/filesystem": "dev-next", - "innmind/time-continuum": "dev-next", - "innmind/io": "dev-next", - "innmind/media-type": "dev-next", - "innmind/url": "dev-next", - "innmind/validation": "dev-next", - "innmind/ip": "dev-next" + "innmind/immutable": "~6.0", + "innmind/filesystem": "~9.0", + "innmind/time-continuum": "~5.0" }, "autoload": { "psr-4": { @@ -31,7 +26,7 @@ } }, "require-dev": { - "innmind/static-analysis": "^1.2.1", + "innmind/static-analysis": "~1.3", "innmind/black-box": "~6.1", "innmind/coding-standard": "~2.0" } diff --git a/proofs/gzip.php b/proofs/gzip.php index c4b9531..fe0317d 100644 --- a/proofs/gzip.php +++ b/proofs/gzip.php @@ -46,14 +46,14 @@ static function($assert, $file) { ->number( $content ->chunks() - ->fold(new Concat) + ->fold(Concat::monoid) ->toEncoding(Encoding::ascii) ->length(), ) ->greaterThan( $compressed ->chunks() - ->fold(new Concat) + ->fold(Concat::monoid) ->toEncoding(Encoding::ascii) ->length(), ); @@ -98,8 +98,8 @@ static function($assert, $file) { $content = $decompress($compress($original)); $assert->same( - $original->chunks()->fold(new Concat)->toString(), - $content->chunks()->fold(new Concat)->toString(), + $original->chunks()->fold(Concat::monoid)->toString(), + $content->chunks()->fold(Concat::monoid)->toString(), ); }, ); diff --git a/proofs/tar.php b/proofs/tar.php index 37c4ac8..78d4052 100644 --- a/proofs/tar.php +++ b/proofs/tar.php @@ -7,6 +7,7 @@ Name, File, Directory, + Recover, }; use Innmind\TimeContinuum\Clock; use Innmind\Url\Path; @@ -27,8 +28,12 @@ static function($assert, $name) { $clock = Clock::live(); $path = \rtrim(\sys_get_temp_dir(), '/').'/innmind/encoding/'; - $tmp = Adapter::mount(Path::of($path))->unwrap(); - $adapter = Adapter::mount(Path::of('fixtures/'))->unwrap(); + $tmp = Adapter::mount(Path::of($path)) + ->recover(Recover::mount(...)) + ->unwrap(); + $adapter = Adapter::mount(Path::of('fixtures/')) + ->recover(Recover::mount(...)) + ->unwrap(); $tar = $adapter ->get(Name::of($name)) ->map(static fn($file) => $file->rename(Name::of('other-'.$name))) @@ -67,8 +72,12 @@ static function($assert, $name) { static function($assert) { $clock = Clock::live(); $path = \rtrim(\sys_get_temp_dir(), '/').'/innmind/encoding/'; - $tmp = Adapter::mount(Path::of($path))->unwrap(); - $adapter = Adapter::mount(Path::of('./'))->unwrap(); + $tmp = Adapter::mount(Path::of($path)) + ->recover(Recover::mount(...)) + ->unwrap(); + $adapter = Adapter::mount(Path::of('./')) + ->recover(Recover::mount(...)) + ->unwrap(); $tar = $adapter ->get(Name::of('fixtures')) ->map(Tar::encode($clock)) @@ -142,8 +151,12 @@ static function($assert, $name1, $name2) { $clock = Clock::live(); $path = \rtrim(\sys_get_temp_dir(), '/').'/innmind/encoding/'; - $tmp = Adapter::mount(Path::of($path))->unwrap(); - $adapter = Adapter::mount(Path::of('./'))->unwrap(); + $tmp = Adapter::mount(Path::of($path)) + ->recover(Recover::mount(...)) + ->unwrap(); + $adapter = Adapter::mount(Path::of('./')) + ->recover(Recover::mount(...)) + ->unwrap(); $tar = $adapter ->get(Name::of('fixtures')) ->map(Directory::of($name2)->add(...)) @@ -221,7 +234,9 @@ static function($assert, $name1, $name2) { static function($assert, $file) { $clock = Clock::live(); $path = \rtrim(\sys_get_temp_dir(), '/').'/innmind/encoding/'; - $tmp = Adapter::mount(Path::of($path))->unwrap(); + $tmp = Adapter::mount(Path::of($path)) + ->recover(Recover::mount(...)) + ->unwrap(); // make sure to avoid conflicts when trying to unarchive $tmp->remove($file->name()); From 85886e7786206134f2fefebd7ec03648407ee672 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sun, 1 Feb 2026 17:50:56 +0100 Subject: [PATCH 4/9] fix warnings --- proofs/tar.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proofs/tar.php b/proofs/tar.php index 78d4052..3aaefde 100644 --- a/proofs/tar.php +++ b/proofs/tar.php @@ -44,7 +44,7 @@ static function($assert, $name) { ); $tar = File::named('test.tar', $tar); - $tmp->add($tar); + $_ = $tmp->add($tar)->unwrap(); $exitCode = null; \exec("tar -xf $path/test.tar --directory=$path", result_code: $exitCode); @@ -88,7 +88,7 @@ static function($assert) { $tar = File::named('fixtures.tar', $tar); - $tmp->add($tar); + $_ = $tmp->add($tar)->unwrap(); $exitCode = null; \exec("tar -xf $path/fixtures.tar --directory=$path", result_code: $exitCode); @@ -169,7 +169,7 @@ static function($assert, $name1, $name2) { $tar = File::named('names.tar', $tar); - $tmp->add($tar); + $_ = $tmp->add($tar)->unwrap(); $exitCode = null; \exec("tar -xf $path/names.tar --directory=$path", result_code: $exitCode); @@ -239,11 +239,11 @@ static function($assert, $file) { ->unwrap(); // make sure to avoid conflicts when trying to unarchive - $tmp->remove($file->name()); + $_ = $tmp->remove($file->name())->unwrap(); $tar = Tar::encode($clock)($file); $tar = File::named('shape.tar', $tar); - $tmp->add($tar); + $_ = $tmp->add($tar)->unwrap(); $exitCode = null; \exec("tar -xf '$path/shape.tar' --directory=$path", result_code: $exitCode); From 0b188bf7a6e739525811a2af4ba0e4feb5953594 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sun, 1 Feb 2026 17:51:29 +0100 Subject: [PATCH 5/9] add missing line in changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32a76ce..ef9753f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Changed - Requires PHP `8.4` +- Requires `innmind/filesystem:~9.0` ## 2.0.0 - 2025-04-16 From 801fd95f4a3edee47ac7073d75bf135bf351cd8e Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sun, 1 Feb 2026 17:53:05 +0100 Subject: [PATCH 6/9] replace innmind/time-continuum by innmind/time --- CHANGELOG.md | 1 + composer.json | 2 +- proofs/tar.php | 4 ++-- src/Tar.php | 2 +- src/Tar/Encode.php | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef9753f..1d72238 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Requires PHP `8.4` - Requires `innmind/filesystem:~9.0` +- Requires `innmind/time:~1.0` ## 2.0.0 - 2025-04-16 diff --git a/composer.json b/composer.json index 6d0befe..88f8fa5 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "php": "~8.4", "innmind/immutable": "~6.0", "innmind/filesystem": "~9.0", - "innmind/time-continuum": "~5.0" + "innmind/time": "~1.0" }, "autoload": { "psr-4": { diff --git a/proofs/tar.php b/proofs/tar.php index 3aaefde..213291d 100644 --- a/proofs/tar.php +++ b/proofs/tar.php @@ -9,7 +9,7 @@ Directory, Recover, }; -use Innmind\TimeContinuum\Clock; +use Innmind\Time\Clock; use Innmind\Url\Path; use Innmind\Immutable\{ Str, @@ -266,7 +266,7 @@ static function($assert, $file) { $assert->true($tmp->contains($file->name())); // for simplicity no recursive assertions on nested directories - $file + $_ = $file ->all() ->keep(Instance::of(File::class)) ->foreach( diff --git a/src/Tar.php b/src/Tar.php index 5b2a775..d4a7b26 100644 --- a/src/Tar.php +++ b/src/Tar.php @@ -3,7 +3,7 @@ namespace Innmind\Encoding; -use Innmind\TimeContinuum\Clock; +use Innmind\Time\Clock; final class Tar { diff --git a/src/Tar/Encode.php b/src/Tar/Encode.php index 81fc496..97a7fa4 100644 --- a/src/Tar/Encode.php +++ b/src/Tar/Encode.php @@ -8,7 +8,7 @@ File\Content, Directory, }; -use Innmind\TimeContinuum\{ +use Innmind\Time\{ Clock, Format, }; From ce89e43ee5125545f271d287f5a132b82e5a0e72 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sun, 1 Feb 2026 17:54:03 +0100 Subject: [PATCH 7/9] add extensive CI --- .github/workflows/extensive.yml | 12 ++++++++++++ blackbox.php | 4 ++++ 2 files changed, 16 insertions(+) create mode 100644 .github/workflows/extensive.yml diff --git a/.github/workflows/extensive.yml b/.github/workflows/extensive.yml new file mode 100644 index 0000000..257f139 --- /dev/null +++ b/.github/workflows/extensive.yml @@ -0,0 +1,12 @@ +name: Extensive CI + +on: + push: + tags: + - '*' + paths: + - '.github/workflows/extensive.yml' + +jobs: + blackbox: + uses: innmind/github-workflows/.github/workflows/extensive.yml@main diff --git a/blackbox.php b/blackbox.php index 3785ad1..78fd2a0 100644 --- a/blackbox.php +++ b/blackbox.php @@ -10,6 +10,10 @@ }; Application::new($argv) + ->when( + \getenv('BLACKBOX_SET_SIZE') !== false, + static fn(Application $app) => $app->scenariiPerProof((int) \getenv('BLACKBOX_SET_SIZE')), + ) ->when( \getenv('ENABLE_COVERAGE') !== false, static fn(Application $app) => $app From f6b0b4bb518597a3d68060b2f6306bd0b0485289 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sun, 1 Feb 2026 17:58:58 +0100 Subject: [PATCH 8/9] fix documentation --- README.md | 6 +++--- documentation/use-cases/backup.md | 10 +++++++--- documentation/use-cases/compressed-at-rest.md | 15 +++++++++------ documentation/use-cases/http.md | 1 + 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index ff8e8a5..a2fb67d 100644 --- a/README.md +++ b/README.md @@ -19,17 +19,17 @@ composer require innmind/encoding ```php use Innmind\Filesystem\{ - Adapter\Filesystem, + Adapter, Name, }; -use Innmind\TimeContinuum\Clock; +use Innmind\Time\Clock; use Innmind\Url\Path; use Innmind\Encoding\{ Gzip, Tar, }; -$adapter = Filesystem::mount(Path::of('some/directory/')); +$adapter = Adapter::mount(Path::of('some/directory/'))->unwrap(); $tar = $adapter ->get(Name::of('data')) ->map(Tar::encode(Clock::live())) diff --git a/documentation/use-cases/backup.md b/documentation/use-cases/backup.md index a5c9363..0cc37cc 100644 --- a/documentation/use-cases/backup.md +++ b/documentation/use-cases/backup.md @@ -25,9 +25,13 @@ $os = Factory::build(); $data = $os ->filesystem() ->mount(Path::of('path/to/stored/data')) + ->unwrap() ->root() ->rename(Name::of('data')); -$sql = $os->remote()->sql(Url::of('mysql://{user}:{password}@localhost:3306/{database}')); +$sql = $os + ->remote() + ->sql(Url::of('mysql://{user}:{password}@localhost:3306/{database}')) + ->unwrap(); $users = $sql(SQL::onDemand('SELECT * FROM users')) ->map(static fn($row) => \implode( "\t", @@ -53,7 +57,7 @@ Up to this point `$archive` represents a file content but no real operation has ```php use Innmind\Http\{ - ResponseSender, + Response\Sender\Native as ResponseSender, Response, Response\StatusCode, ProtocolVersion, @@ -63,7 +67,7 @@ use Innmind\Http\{ $archive = /* see above */; -(new ResponseSender($os->clock()))(Response::of( +ResponseSender::of($os->clock())(Response::of( StatusCode::ok, ProtocolVersion::v11, Headers::of( diff --git a/documentation/use-cases/compressed-at-rest.md b/documentation/use-cases/compressed-at-rest.md index 7437d7f..422af24 100644 --- a/documentation/use-cases/compressed-at-rest.md +++ b/documentation/use-cases/compressed-at-rest.md @@ -15,7 +15,7 @@ use Innmind\Url\Path; use Innmind\Http\{ Response, Response\StatusCode, - ResponseSender, + Response\Sender\Native as ResponseSender, }; $os = Factory::build(); @@ -25,14 +25,16 @@ $response = $serverRequest ->files() ->under('tsv') ->get('users') - ->map(static fn($file) => $file->content() + ->map(static fn($file) => $file->content()) ->map(Gzip::compress()) ->map(static fn($content) => File::named('users.tsv.gz', $content)) ->map( static fn($file) => $os ->filesystem() ->mount(Path::of('path/to/stored/data/')) - ->add($file)), + ->unwrap() + ->add($file) + ->unwrap(), ) ->match( static fn() => Response::of( @@ -45,7 +47,7 @@ $response = $serverRequest ), ); -(new ResponseSender($os->clock()))($response); +ResponseSender::of($os->clock())($response); ``` This code will take any file uploaded in the key `tsv[users]`, gzip it and write it in the `path/to/stored/data/` directory under the name `users.tsv.gz` and return a `201` HTTP response. If the upload failed it will return a `400` response. @@ -61,7 +63,7 @@ use Innmind\Url\Path; use Innmind\Http\{ Response, Response\StatusCode, - ResponseSender, + Response\Sender\Native as ResponseSender, Headers, Header\ContentType, Header\ContentEncoding, @@ -84,6 +86,7 @@ $acceptGzip = $serverRequest $response = $os ->filesystem() ->mount(Path::of('path/to/stored/data/')) + ->unwrap() ->get(Name::of('users.tsv.gz')) ->map(static fn($file) => match ($acceptGzip) { true => Response::of( @@ -112,7 +115,7 @@ $response = $os ), ); -(new ResponseSender($os->clock()))($response); +ResponseSender::of($os->clock())($response); ``` Here we try to load the `users.tsv.gz` file, we check if the caller accepts a gzipped content, if so we return the file as is via a `200` HTTP response and if not we decompress the file and return it. And if the file doesn't exist we return a `400` response. diff --git a/documentation/use-cases/http.md b/documentation/use-cases/http.md index 20822a5..5bd3733 100644 --- a/documentation/use-cases/http.md +++ b/documentation/use-cases/http.md @@ -21,6 +21,7 @@ $http = $os->remote()->http(); $os ->filesystem() ->mount(Path::of('path/to/stored/data/')) + ->unwrap() ->get(Name::of('somefile.txt')) ->map(static fn($file) => $file->content()); ->map(Gzip::compress()) From 1e9469c37f5969a838dd38735e485a5c8de6a8a3 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sun, 1 Feb 2026 18:01:16 +0100 Subject: [PATCH 9/9] bump minimum version of blackbox --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 88f8fa5..5423ef1 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ }, "require-dev": { "innmind/static-analysis": "~1.3", - "innmind/black-box": "~6.1", + "innmind/black-box": "~6.9", "innmind/coding-standard": "~2.0" } }