Issues (224)

src/Phar/Differ/ChecksumDiffer.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the box project.
7
 *
8
 * (c) Kevin Herrera <[email protected]>
9
 *     Théo Fidry <[email protected]>
10
 *
11
 * This source file is subject to the MIT license that is bundled
12
 * with this source code in the file LICENSE.
13
 */
14
15
namespace KevinGH\Box\Phar\Differ;
16
17
use Fidry\Console\IO;
18
use KevinGH\Box\Phar\PharInfo;
19
use UnexpectedValueException;
20
use ValueError;
21
use function hash;
22
use function implode;
23
24
final readonly class ChecksumDiffer implements Differ
0 ignored issues
show
A parse error occurred: Syntax error, unexpected T_READONLY, expecting T_CLASS on line 24 at column 6
Loading history...
25
{
26
    public function __construct(
27
        private string $checksumAlgorithm,
28
    ) {
29
    }
30
31
    public function diff(
32
        PharInfo $pharInfoA,
33
        PharInfo $pharInfoB,
34
        IO $io,
35
    ): void {
36
        $diff = self::computeDiff(
37
            $pharInfoA,
38
            $pharInfoB,
39
            $this->checksumAlgorithm,
40
        );
41
42
        $io->writeln($diff ?? Differ::NO_DIFF_MESSAGE);
43
    }
44
45
    private static function computeDiff(
46
        PharInfo $pharInfoA,
47
        PharInfo $pharInfoB,
48
        string $checksumAlgorithm,
49
    ): ?string {
50
        $pharInfoAFileHashes = self::getFileHashesByRelativePathname(
51
            $pharInfoA,
52
            $checksumAlgorithm,
53
        );
54
        $pharInfoBFileHashes = self::getFileHashesByRelativePathname(
55
            $pharInfoB,
56
            $checksumAlgorithm,
57
        );
58
        $output = [
59
            '<diff-expected>--- PHAR A</diff-expected>',
60
            '<diff-actual>+++ PHAR B</diff-actual>',
61
            '@@ @@',
62
        ];
63
64
        foreach ($pharInfoAFileHashes as $filePath => $fileAHash) {
65
            if (!array_key_exists($filePath, $pharInfoBFileHashes)) {
66
                $output[] = $filePath;
67
                $output[] = sprintf(
68
                    "\t<diff-expected>- %s</diff-expected>",
69
                    $fileAHash,
70
                );
71
72
                continue;
73
            }
74
75
            $fileBHash = $pharInfoBFileHashes[$filePath];
76
            unset($pharInfoBFileHashes[$filePath]);
77
78
            if ($fileAHash === $fileBHash) {
79
                continue;
80
            }
81
82
            $output[] = $filePath;
83
            $output[] = sprintf(
84
                "\t<diff-expected>- %s</diff-expected>",
85
                $fileAHash,
86
            );
87
            $output[] = sprintf(
88
                "\t<diff-actual>+ %s</diff-actual>",
89
                $fileBHash,
90
            );
91
        }
92
93
        foreach ($pharInfoBFileHashes as $filePath => $fileBHash) {
94
            $output[] = $filePath;
95
            $output[] = sprintf(
96
                "\t<diff-actual>+ %s</diff-actual>",
97
                $fileBHash,
98
            );
99
        }
100
101
        return 3 === count($output) ? null : implode("\n", $output);
102
    }
103
104
    /**
105
     * @return array<string, string>
106
     */
107
    private static function getFileHashesByRelativePathname(
108
        PharInfo $pharInfo,
109
        string $algorithm,
110
    ): array {
111
        $hashFiles = [];
112
113
        try {
114
            $hashFiles[$pharInfo->getStubPath()] = hash(
115
                $algorithm,
116
                $pharInfo->getStubContent(),
117
            );
118
119
            foreach ($pharInfo->getFiles() as $file) {
120
                $hashFiles[$file->getRelativePathname()] = hash_file(
121
                    $algorithm,
122
                    $file->getPathname(),
123
                );
124
            }
125
        } catch (ValueError) {
126
            throw new UnexpectedValueException(
127
                sprintf(
128
                    'Unexpected algorithm "%s". Please pick a registered hashing algorithm (checksum `hash_algos()`).',
129
                    $algorithm,
130
                ),
131
            );
132
        }
133
134
        return $hashFiles;
135
    }
136
}
137