Skip to content

Commit

Permalink
Merge 7805491 into f32efe4
Browse files Browse the repository at this point in the history
  • Loading branch information
azjezz committed Mar 5, 2021
2 parents f32efe4 + 7805491 commit b503e21
Show file tree
Hide file tree
Showing 53 changed files with 2,240 additions and 1 deletion.
14 changes: 14 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,26 @@
<directory>src</directory>
</include>
<exclude>
<!-- Internal -->
<file>src/preload.php</file>
<file>src/bootstrap.php</file>
<directory>src/Psl/Internal</directory>

<!-- Base Exceptions -->
<directory>src/Psl/Exception</directory>

<!-- Constants -->
<file>src/Psl/Str/constants.php</file>
<file>src/Psl/Math/constants.php</file>
<file>src/Psl/Filesystem/constants.php</file>

<!-- Things that are not easily tested -->
<file>src/Psl/Filesystem/get_group.php</file>
<file>src/Psl/Filesystem/change_group.php</file>
<file>src/Psl/Filesystem/Internal/change_group.php</file>
<file>src/Psl/Filesystem/get_owner.php</file>
<file>src/Psl/Filesystem/change_owner.php</file>
<file>src/Psl/Filesystem/Internal/change_owner.php</file>
</exclude>
<report>
<clover outputFile="tests/logs/clover.xml"/>
Expand Down
11 changes: 11 additions & 0 deletions src/Psl/Filesystem/Exception/ExceptionInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Psl\Filesystem\Exception;

use Psl\Exception;

interface ExceptionInterface extends Exception\ExceptionInterface
{
}
11 changes: 11 additions & 0 deletions src/Psl/Filesystem/Exception/RuntimeException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Psl\Filesystem\Exception;

use Psl\Exception;

class RuntimeException extends Exception\RuntimeException implements ExceptionInterface
{
}
46 changes: 46 additions & 0 deletions src/Psl/Filesystem/Internal/change_group.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace Psl\Filesystem\Internal;

use Psl\Filesystem;
use Psl\Filesystem\Exception;
use Psl\Internal;
use Psl\Str;

use function chgrp;
use function lchgrp;

/**
* @param iterable<string> $files
* @param string|int $group
*
* @throws Exception\RuntimeException If unable to change the ownership for
* the given file.
*
* @internal
*/
function change_group(iterable $files, $group, bool $recursive = false): void
{
foreach ($files as $file) {
if ($recursive && Filesystem\is_directory($file) && !Filesystem\is_symbolic_link($file)) {
change_group(Filesystem\read_directory($file), $group, true);
}

if (Filesystem\is_symbolic_link($file)) {
$fun = static fn(): bool => lchgrp($file, $group);
} else {
$fun = static fn(): bool => chgrp($file, $group);
}

[$success, $error] = Internal\box($fun);
if (!$success) {
throw new Exception\RuntimeException(Str\format(
'Failed to change the group for file "%s": %s',
$file,
$error ?? 'internal error.',
));
}
}
}
46 changes: 46 additions & 0 deletions src/Psl/Filesystem/Internal/change_owner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace Psl\Filesystem\Internal;

use Psl\Filesystem;
use Psl\Filesystem\Exception;
use Psl\Internal;
use Psl\Str;

use function chown;
use function lchown;

/**
* @param iterable<string> $files
* @param string|int $user
*
* @throws Exception\RuntimeException If unable to change the ownership for
* the given file.
*
* @internal
*/
function change_owner(iterable $files, $user, bool $recursive = false): void
{
foreach ($files as $file) {
if ($recursive && Filesystem\is_directory($file) && !Filesystem\is_symbolic_link($file)) {
change_owner(Filesystem\read_directory($file), $user, true);
}

if (Filesystem\is_symbolic_link($file)) {
$fun = static fn(): bool => lchown($file, $user);
} else {
$fun = static fn(): bool => chown($file, $user);
}

[$success, $error] = Internal\box($fun);
if (!$success) {
throw new Exception\RuntimeException(Str\format(
'Failed to change owner for file "%s": %s',
$file,
$error ?? 'internal error.',
));
}
}
}
40 changes: 40 additions & 0 deletions src/Psl/Filesystem/Internal/change_permissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Psl\Filesystem\Internal;

use Psl\Filesystem;
use Psl\Filesystem\Exception;
use Psl\Internal;
use Psl\Str;

use function chmod;

/**
* @param iterable<string> $files
*
* @throws Exception\RuntimeException If unable to change the ownership for
* the given file.
*
* @internal
*/
function change_permissions(iterable $files, int $permission, bool $recursive = false): void
{
foreach ($files as $file) {
if ($recursive && Filesystem\is_directory($file) && !Filesystem\is_symbolic_link($file)) {
change_permissions(Filesystem\read_directory($file), $permission, true);
}

[$success, $error] = Internal\box(static fn(): bool => chmod($file, $permission));
// @codeCoverageIgnoreStart
if (!$success) {
throw new Exception\RuntimeException(Str\format(
'Failed to change permissions for file "%s": %s',
$file,
$error ?? 'internal error.',
));
}
// @codeCoverageIgnoreEnd
}
}
18 changes: 18 additions & 0 deletions src/Psl/Filesystem/canonicalize.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Psl\Filesystem;

use function realpath;

/**
* Returns canonicalized absolute pathname.
*
* @return string|null The canonicalized absolute pathname on success.
* The resulting path will have no symbolic link, '/./' or '/../' components.
*/
function canonicalize(string $path): ?string
{
return realpath($path) ?: null;
}
22 changes: 22 additions & 0 deletions src/Psl/Filesystem/change_group.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Psl\Filesystem;

use Psl;

/**
* Change the group ownership of $filename.
*
* @param bool $recursive Whether change the group ownership recursively or not.
*
* @throws Exception\RuntimeException If unable to change the group ownership for $filename.
* @throws Psl\Exception\InvariantViolationException If $filename does not exist.
*/
function change_group(string $filename, int $group, bool $recursive = false): void
{
Psl\invariant(exists($filename), '$filename does not exist.');

Internal\change_owner([$filename], $group, $recursive);
}
22 changes: 22 additions & 0 deletions src/Psl/Filesystem/change_owner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Psl\Filesystem;

use Psl;

/**
* Change the owner of $filename.
*
* @param bool $recursive Whether change the owner recursively or not.
*
* @throws Exception\RuntimeException If unable to change the ownership for $filename.
* @throws Psl\Exception\InvariantViolationException If $filename does not exist.
*/
function change_owner(string $filename, int $user, bool $recursive = false): void
{
Psl\invariant(exists($filename), '$filename does not exist.');

Internal\change_owner([$filename], $user, $recursive);
}
22 changes: 22 additions & 0 deletions src/Psl/Filesystem/change_permissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Psl\Filesystem;

use Psl;

/**
* Changes mode permission of $filename.
*
* @param bool $recursive Whether change the mode recursively or not.
*
* @throws Exception\RuntimeException If unable to change the mode for the given $filename.
* @throws Psl\Exception\InvariantViolationException If $filename does not exists.
*/
function change_permissions(string $filename, int $permissions, bool $recursive = false): void
{
Psl\invariant(exists($filename), '$filename does not exist.');

Internal\change_permissions([$filename], $permissions, $recursive);
}
12 changes: 12 additions & 0 deletions src/Psl/Filesystem/constants.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Psl\Filesystem;

use const DIRECTORY_SEPARATOR;

/**
* @var string SEPARATOR
*/
const SEPARATOR = DIRECTORY_SEPARATOR;
72 changes: 72 additions & 0 deletions src/Psl/Filesystem/copy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);

namespace Psl\Filesystem;

use Psl;
use Psl\Internal;
use Psl\Str;

use function fclose;
use function fopen;
use function stream_copy_to_stream;

/**
* Change the group ownership of $filename.
*
* @throws Exception\RuntimeException If unable to change the group ownership for $filename.
* @throws Psl\Exception\InvariantViolationException If $source does not exist or is not readable.
*/
function copy(string $source, string $destination, bool $overwrite = false): void
{
Psl\invariant(is_file($source) && is_readable($source), '$source does not exist or is not readable.');

if (!$overwrite && is_file($destination)) {
return;
}

/**
* @psalm-suppress InvalidArgument - callable is not pure..
*/
$source_stream = Internal\suppress(static fn() => fopen($source, 'rb'));
// @codeCoverageIgnoreStart
if (false === $source_stream) {
throw new Exception\RuntimeException('Failed to open $source file for reading');
}
// @codeCoverageIgnoreEnd

/**
* @psalm-suppress InvalidArgument - callable is not pure..
*/
$destination_stream = Internal\suppress(static fn() => fopen($destination, 'wb'));
// @codeCoverageIgnoreStart
if (false === $destination_stream) {
throw new Exception\RuntimeException('Failed to open $destination file for writing.');
}
// @codeCoverageIgnoreEnd

$copied_bytes = stream_copy_to_stream($source_stream, $destination_stream);
fclose($source_stream);
fclose($destination_stream);

$total_bytes = file_size($source);

// preserve executable permission bits
change_permissions(
$destination,
get_permissions($destination) | (get_permissions($source) & 0111)
);

// @codeCoverageIgnoreStart
if ($copied_bytes !== $total_bytes) {
throw new Exception\RuntimeException(Str\format(
'Failed to copy the whole content of "%s" to "%s" ( %g of %g bytes copied ).',
$source,
$destination,
$copied_bytes,
$total_bytes
));
}
// @codeCoverageIgnoreEnd
}
32 changes: 32 additions & 0 deletions src/Psl/Filesystem/create_directory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Psl\Filesystem;

use Psl\Internal;
use Psl\Str;

use function mkdir;

/**
* Create the directory specified by $directory.
*
* @throws Exception\RuntimeException If unable to create the directory.
*/
function create_directory(string $directory, int $permissions = 0777): void
{
[$result, $error_message] = Internal\box(
static fn() => mkdir($directory, $permissions, true)
);

// @codeCoverageIgnoreStart
if (false === $result && !is_directory($directory)) {
throw new Exception\RuntimeException(Str\format(
'Failed to create directory "%s": %s.',
$directory,
$error_message ?? 'internal error'
));
}
// @codeCoverageIgnoreEnd
}

0 comments on commit b503e21

Please sign in to comment.