diff --git a/fixtures/info/tree-phar.phar b/fixtures/info/tree-phar.phar
index cd4b5356f..db8a76325 100644
Binary files a/fixtures/info/tree-phar.phar and b/fixtures/info/tree-phar.phar differ
diff --git a/src/Console/Command/Build.php b/src/Console/Command/Build.php
index ab3495374..4970b39d4 100644
--- a/src/Console/Command/Build.php
+++ b/src/Console/Command/Build.php
@@ -17,8 +17,8 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
-use const E_USER_DEPRECATED;
use function trigger_error;
+use const E_USER_DEPRECATED;
/**
* @deprecated
diff --git a/src/Console/Command/Compile.php b/src/Console/Command/Compile.php
index 077c9e509..75ee79e11 100644
--- a/src/Console/Command/Compile.php
+++ b/src/Console/Command/Compile.php
@@ -47,6 +47,7 @@
use function count;
use function decoct;
use function explode;
+use function filesize;
use function function_exists;
use function get_class;
use function implode;
@@ -56,7 +57,7 @@
use function KevinGH\Box\FileSystem\make_path_relative;
use function KevinGH\Box\FileSystem\remove;
use function KevinGH\Box\FileSystem\rename;
-use function KevinGH\Box\formatted_filesize;
+use function KevinGH\Box\format_size;
use function KevinGH\Box\get_phar_compression_algorithms;
use function posix_setrlimit;
use function putenv;
@@ -828,7 +829,9 @@ private function logEndBuilding(BuildLogger $logger, SymfonyStyle $io, Box $box,
sprintf(
'PHAR: %s (%s)',
$box->count() > 1 ? $box->count().' files' : $box->count().' file',
- formatted_filesize($path)
+ format_size(
+ filesize($path)
+ )
)
.PHP_EOL
.'You can inspect the generated PHAR with the "info" command.'
diff --git a/src/Console/Command/Info.php b/src/Console/Command/Info.php
index 2e5d17f5e..5e9f267a5 100644
--- a/src/Console/Command/Info.php
+++ b/src/Console/Command/Info.php
@@ -14,6 +14,7 @@
namespace KevinGH\Box\Console\Command;
+use Assert\Assertion;
use DateTimeImmutable;
use DirectoryIterator;
use Phar;
@@ -34,11 +35,12 @@
use function array_sum;
use function count;
use function end;
+use function filesize;
use function is_array;
use function iterator_to_array;
use function KevinGH\Box\FileSystem\copy;
use function KevinGH\Box\FileSystem\remove;
-use function KevinGH\Box\formatted_filesize;
+use function KevinGH\Box\format_size;
use function key;
use function realpath;
use function sprintf;
@@ -56,6 +58,7 @@ final class Info extends Command
private const LIST_OPT = 'list';
private const METADATA_OPT = 'metadata';
private const MODE_OPT = 'mode';
+ private const DEPTH_OPT = 'depth';
/**
* The list of recognized compression algorithms.
@@ -121,10 +124,17 @@ protected function configure(): void
$this->addOption(
self::MODE_OPT,
'm',
- InputOption::VALUE_OPTIONAL,
+ InputOption::VALUE_REQUIRED,
'The listing mode. (default: indent, options: indent, flat)',
'indent'
);
+ $this->addOption(
+ self::DEPTH_OPT,
+ 'd',
+ InputOption::VALUE_REQUIRED,
+ 'The depth of the tree displayed',
+ -1
+ );
}
/**
@@ -168,6 +178,10 @@ public function execute(InputInterface $input, OutputInterface $output): int
public function showInfo(string $file, string $originalFile, InputInterface $input, OutputInterface $output, SymfonyStyle $io): int
{
+ $depth = (int) $input->getOption(self::DEPTH_OPT);
+
+ Assertion::greaterOrEqualThan($depth, -1, 'Expected the depth to be a positive integer or -1, got "%d"');
+
try {
try {
$phar = new Phar($file);
@@ -178,11 +192,16 @@ public function showInfo(string $file, string $originalFile, InputInterface $inp
return $this->showPharInfo(
$phar,
$input->getOption(self::LIST_OPT),
+ $depth,
'indent' === $input->getOption(self::MODE_OPT),
$output,
$io
);
} catch (Throwable $throwable) {
+ if ($output->isDebug()) {
+ throw $throwable;
+ }
+
$io->error(
sprintf(
'Could not read the file "%s".',
@@ -214,8 +233,14 @@ private function showGlobalInfo(OutputInterface $output, SymfonyStyle $io): int
/**
* @param Phar|PharData $phar
*/
- private function showPharInfo($phar, bool $content, bool $indent, OutputInterface $output, SymfonyStyle $io): int
- {
+ private function showPharInfo(
+ $phar,
+ bool $content,
+ int $depth,
+ bool $indent,
+ OutputInterface $output,
+ SymfonyStyle $io
+ ): int {
$signature = $phar->getSignature();
$this->showPharGlobalInfo($phar, $io, $signature);
@@ -226,6 +251,8 @@ private function showPharInfo($phar, bool $content, bool $indent, OutputInterfac
$this->renderContents(
$output,
$phar,
+ 0,
+ $depth,
$indent ? 0 : false,
$root,
$phar,
@@ -320,7 +347,9 @@ private function showPharGlobalInfo($phar, SymfonyStyle $io, $signature): void
sprintf(
'Contents:%s (%s)',
1 === $totalCount ? ' 1 file' : " $totalCount files",
- formatted_filesize($phar->getPath())
+ format_size(
+ filesize($phar->getPath())
+ )
)
);
}
@@ -361,11 +390,17 @@ private function render(OutputInterface $output, array $attributes): void
private function renderContents(
OutputInterface $output,
iterable $list,
+ int $depth,
+ int $maxDepth,
$indent,
string $base,
$phar,
string $root
): void {
+ if (-1 !== $maxDepth && $depth > $maxDepth) {
+ return;
+ }
+
foreach ($list as $item) {
$item = $phar[str_replace($root, '', $item->getPathname())];
@@ -386,22 +421,33 @@ private function renderContents(
$output->writeln("$path");
}
} else {
- $compression = ' [NONE]';
+ $compression = '[NONE]';
foreach (self::FILE_ALGORITHMS as $code => $name) {
if ($item->isCompressed($code)) {
- $compression = " [$name]";
+ $compression = "[$name]";
break;
}
}
- $output->writeln($path.$compression);
+ $fileSize = format_size($item->getCompressedSize());
+
+ $output->writeln(
+ sprintf(
+ '%s %s - %s',
+ $path,
+ $compression,
+ $fileSize
+ )
+ );
}
if ($item->isDir()) {
$this->renderContents(
$output,
new DirectoryIterator($item->getPathname()),
+ $depth + 1,
+ $maxDepth,
(false === $indent) ? $indent : $indent + 2,
$base,
$phar,
diff --git a/src/PhpSettingsHandler.php b/src/PhpSettingsHandler.php
index 50dce21be..ec03729df 100644
--- a/src/PhpSettingsHandler.php
+++ b/src/PhpSettingsHandler.php
@@ -17,13 +17,13 @@
use Composer\XdebugHandler\Process;
use Composer\XdebugHandler\XdebugHandler;
use Psr\Log\LoggerInterface;
-use const PHP_EOL;
use function function_exists;
use function getenv;
use function ini_get;
use function KevinGH\Box\FileSystem\append_to_file;
use function sprintf;
use function trim;
+use const PHP_EOL;
/**
* @private
diff --git a/src/functions.php b/src/functions.php
index 699a6e845..94e55771b 100644
--- a/src/functions.php
+++ b/src/functions.php
@@ -56,12 +56,11 @@ function get_phar_compression_algorithm_extension(int $algorithm): ?string
/**
* @private
*/
-function formatted_filesize(string $path): string
+// TODO: add more tests for this
+function format_size(int $size): string
{
- Assertion::file($path);
-
- $size = filesize($path);
$units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
+
$power = $size > 0 ? (int) floor(log($size, 1024)) : 0;
return sprintf(
diff --git a/tests/BoxTest.php b/tests/BoxTest.php
index b1b6b0b8b..fc0c77636 100644
--- a/tests/BoxTest.php
+++ b/tests/BoxTest.php
@@ -16,7 +16,6 @@
use Exception;
use InvalidArgumentException;
-use function iterator_to_array;
use KevinGH\Box\Compactor\FakeCompactor;
use KevinGH\Box\Console\DisplayNormalizer;
use KevinGH\Box\Test\FileSystemTestCase;
@@ -35,6 +34,7 @@
use function extension_loaded;
use function file_put_contents;
use function in_array;
+use function iterator_to_array;
use function KevinGH\Box\FileSystem\canonicalize;
use function KevinGH\Box\FileSystem\dump_file;
use function KevinGH\Box\FileSystem\make_tmp_dir;
diff --git a/tests/ConfigurationFileTest.php b/tests/ConfigurationFileTest.php
index ff1742ca2..7388f233e 100644
--- a/tests/ConfigurationFileTest.php
+++ b/tests/ConfigurationFileTest.php
@@ -17,12 +17,12 @@
use Generator;
use InvalidArgumentException;
use KevinGH\Box\Json\JsonValidationException;
-use const DIRECTORY_SEPARATOR;
use function file_put_contents;
use function KevinGH\Box\FileSystem\dump_file;
use function KevinGH\Box\FileSystem\make_path_absolute;
use function KevinGH\Box\FileSystem\rename;
use function KevinGH\Box\FileSystem\symlink;
+use const DIRECTORY_SEPARATOR;
/**
* @covers \KevinGH\Box\Configuration
diff --git a/tests/ConfigurationTest.php b/tests/ConfigurationTest.php
index 56324f319..8c5c99a63 100644
--- a/tests/ConfigurationTest.php
+++ b/tests/ConfigurationTest.php
@@ -25,11 +25,11 @@
use Phar;
use Seld\JsonLint\ParsingException;
use stdClass;
-use const DIRECTORY_SEPARATOR;
use function file_put_contents;
use function KevinGH\Box\FileSystem\dump_file;
use function KevinGH\Box\FileSystem\remove;
use function KevinGH\Box\FileSystem\rename;
+use const DIRECTORY_SEPARATOR;
/**
* @covers \KevinGH\Box\Configuration
diff --git a/tests/ConfigurationTestCase.php b/tests/ConfigurationTestCase.php
index 38493adf3..6cda8df1c 100644
--- a/tests/ConfigurationTestCase.php
+++ b/tests/ConfigurationTestCase.php
@@ -17,10 +17,10 @@
use KevinGH\Box\Console\ConfigurationHelper;
use KevinGH\Box\Test\FileSystemTestCase;
use stdClass;
-use const DIRECTORY_SEPARATOR;
use function file_put_contents;
use function KevinGH\Box\FileSystem\make_path_absolute;
use function natcasesort;
+use const DIRECTORY_SEPARATOR;
abstract class ConfigurationTestCase extends FileSystemTestCase
{
diff --git a/tests/Console/Command/CompileTest.php b/tests/Console/Command/CompileTest.php
index 73b0ae477..a540db913 100644
--- a/tests/Console/Command/CompileTest.php
+++ b/tests/Console/Command/CompileTest.php
@@ -14,7 +14,6 @@
namespace KevinGH\Box\Console\Command;
-use const DIRECTORY_SEPARATOR;
use DirectoryIterator;
use Generator;
use InvalidArgumentException;
diff --git a/tests/Console/Command/InfoTest.php b/tests/Console/Command/InfoTest.php
index 8dd2daa12..d9175bc5c 100644
--- a/tests/Console/Command/InfoTest.php
+++ b/tests/Console/Command/InfoTest.php
@@ -14,18 +14,24 @@
namespace KevinGH\Box\Console\Command;
+use InvalidArgumentException;
use KevinGH\Box\Console\Application;
use KevinGH\Box\Console\DisplayNormalizer;
use Phar;
use PHPUnit\Framework\TestCase;
+use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Tester\CommandTester;
+use UnexpectedValueException;
use function preg_replace;
use function realpath;
+///**
+// * @covers \KevinGH\Box\Console\Command\Info
+// *
+// * @runTestsInSeparateProcesses
+// */
/**
- * @covers \KevinGH\Box\Console\Command\Info
- *
- * @runTestsInSeparateProcesses
+ * @coversNothing
*/
class InfoTest extends TestCase
{
@@ -178,6 +184,25 @@ public function test_it_cannot_provide_info_about_an_invalid_phar_without_extens
$this->assertSame(1, $this->commandTester->getStatusCode());
}
+ public function test_it_displays_the_error_in_debug_verbosity(): void
+ {
+ $file = self::FIXTURES.'/foo';
+
+ try {
+ $this->commandTester->execute(
+ [
+ 'command' => 'info',
+ 'phar' => $file,
+ ],
+ ['verbosity' => OutputInterface::VERBOSITY_DEBUG]
+ );
+
+ $this->fail('Expected exception to be thrown.');
+ } catch (UnexpectedValueException $exception) {
+ $this->assertStringStartsWith('Cannot create phar', $exception->getMessage());
+ }
+ }
+
public function test_it_provides_info_about_a_targz_phar(): void
{
$pharPath = self::FIXTURES.'/simple-phar.tar.gz';
@@ -287,8 +312,8 @@ public function test_it_provides_a_phar_info_with_the_tree_of_the_content(): voi
API Version: $version
Archive Compression:
- - BZ2 (50.00%)
- - None (50.00%)
+ - BZ2 (33.33%)
+ - None (66.67%)
Signature: {$signature['hash_type']}
Signature Hash: {$signature['hash']}
@@ -298,10 +323,13 @@ public function test_it_provides_a_phar_info_with_the_tree_of_the_content(): voi
'test' => 123,
)
-Contents: 2 files (6.71KB)
+Contents: 3 files (6.75KB)
a/
- bar.php [BZ2]
-foo.php [NONE]
+ bar.php [BZ2] - 60.00B
+b/
+ beta/
+ bar.php [NONE] - 0.00B
+foo.php [NONE] - 19.00B
OUTPUT;
@@ -331,8 +359,176 @@ public function test_it_provides_a_phar_info_with_the_flat_tree_of_the_content()
API Version: $version
Archive Compression:
- - BZ2 (50.00%)
- - None (50.00%)
+ - BZ2 (33.33%)
+ - None (66.67%)
+
+Signature: {$signature['hash_type']}
+Signature Hash: {$signature['hash']}
+
+Metadata:
+array (
+ 'test' => 123,
+)
+
+Contents: 3 files (6.75KB)
+a/bar.php [BZ2] - 60.00B
+b/beta/bar.php [NONE] - 0.00B
+foo.php [NONE] - 19.00B
+
+OUTPUT;
+
+ $this->assertSame($expected, DisplayNormalizer::removeTrailingSpaces($this->commandTester->getDisplay(true)));
+ $this->assertSame(0, $this->commandTester->getStatusCode());
+ }
+
+ public function test_it_can_limit_the_tree_depth(): void
+ {
+ $pharPath = self::FIXTURES.'/tree-phar.phar';
+ $phar = new Phar($pharPath);
+
+ $version = $phar->getVersion();
+ $signature = $phar->getSignature();
+
+ $this->commandTester->execute(
+ [
+ 'command' => 'info',
+ 'phar' => $pharPath,
+ '--list' => true,
+ '--metadata' => true,
+ '--depth' => 0,
+ ]
+ );
+
+ $expected = <<