-
-
Notifications
You must be signed in to change notification settings - Fork 72
/
Copy pathcopy.php
72 lines (60 loc) · 2.09 KB
/
copy.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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
}