Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
Merger
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
3 / 3
5
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 merge
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 patterns
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5/**
6 * Fast Forward Development Tools for PHP projects.
7 *
8 * This file is part of fast-forward/dev-tools project.
9 *
10 * @author   Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
11 * @license  https://opensource.org/licenses/MIT MIT License
12 *
13 * @see      https://github.com/php-fast-forward/
14 * @see      https://github.com/php-fast-forward/dev-tools
15 * @see      https://github.com/php-fast-forward/dev-tools/issues
16 * @see      https://php-fast-forward.github.io/dev-tools/
17 * @see      https://datatracker.ietf.org/doc/html/rfc2119
18 */
19
20namespace FastForward\DevTools\GitIgnore;
21
22/**
23 * Merges ordered .gitignore rules with canonical defaults before consumer overrides.
24 *
25 * Existing patterns MUST retain their order, whitespace and repeated occurrences.
26 */
27  class Merger implements MergerInterface
28{
29    /**
30     * Retains the classifier constructor parameter for compatibility with consumers.
31     */
32    public function __construct(
33        private ClassifierInterface $classifier = new Classifier()
34    ) {}
35
36    /**
37     * Prepends canonical defaults once, allowing later consumer rules to override them.
38     *
39     * @param GitIgnoreInterface $canonical the canonical baseline
40     * @param GitIgnoreInterface $project the consumer rules and destination path
41     */
42    public function merge(GitIgnoreInterface $canonical, GitIgnoreInterface $project): GitIgnoreInterface
43    {
44        $canonicalEntries = $this->patterns($canonical->entries());
45        $projectEntries = $this->patterns($project->entries());
46
47        if (array_slice($projectEntries, 0, count($canonicalEntries)) === $canonicalEntries) {
48            return new GitIgnore($project->path(), $projectEntries);
49        }
50
51        return new GitIgnore($project->path(), [...$canonicalEntries, ...$projectEntries]);
52    }
53
54    /**
55     * Removes only blank lines and comments, never normalizing pattern whitespace.
56     *
57     * @param list<string> $entries the raw rules
58     *
59     * @return list<string>
60     */
61    private function patterns(array $entries): array
62    {
63        return array_values(array_filter(
64            $entries,
65            static fn(string $entry): bool => '' !== trim($entry) && ! str_starts_with($entry, '#'),
66        ));
67    }
68}