biurad/php-git-scm

View on GitHub
src/Commit/Tree.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php declare(strict_types=1);

/*
 * This file is part of Biurad opensource projects.
 *
 * @copyright 2022 Biurad Group (https://biurad.com/)
 * @license   https://opensource.org/licenses/BSD-3-Clause License
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Biurad\Git\Commit;

use Biurad\Git\{GitObject, Repository};

/**
 * The Tree object represents a Git tree object.
 *
 * @author Divine Niiquaye Ibok <divineibok@gmail.com>
 */
class Tree extends GitObject
{
    protected bool $initialized = false;
    protected array $entries = [];

    public function __construct(Repository $repository, string $hash = null, protected ?int $mode = null)
    {
        parent::__construct($repository, $hash);
    }

    public function getMode(): ?int
    {
        return $this->mode;
    }

    /**
     * @return array<string,Blob|CommitRef|Tree> An associative array name => $object
     */
    public function getEntries(): array
    {
        $this->doInitialize();

        return $this->entries;
    }

    public function has(string $entry): bool
    {
        $this->doInitialize();

        return isset($this->entries[$entry]);
    }

    public function get(string $entry): Blob|Tree|CommitRef
    {
        $this->doInitialize();

        return $this->entries[$entry] ?? throw new \InvalidArgumentException(\sprintf('Tree entry "%s" does not exist.', $entry));
    }

    /**
     * Get a sub-tree of a given path.
     */
    public function getSubTree(string $path): Blob|Tree|CommitRef
    {
        $tree = $this;

        foreach (\explode('/', \ltrim($path, '/')) as $segment) {
            if (!empty($segment)) {
                $tree = $tree->get($segment);
            }
        }

        return $tree;
    }

    protected function doInitialize(): void
    {
        if ($this->initialized) {
            return;
        }

        $o = $this->repository->run('ls-tree', [$this->__toString(),'--format=%(objectmode) %(objecttype) %(objectname) %(path)']);

        if (empty($o) || 0 !== $this->repository->getExitCode()) {
            throw new \RuntimeException(\sprintf('Failed to get tree data for "%s"', $this->__toString()));
        }

        foreach (\explode("\n", $o) as $line) {
            if (empty($line)) {
                continue;
            }
            [$a, $b, $c, $d] = \explode(' ', $line, 4);
            $object = null;

            if ('tree' === $b) {
                $object = new self($this->repository, $c, (int) $a);
            } elseif ('blob' === $b) {
                $object = new Blob($this->repository, $c, (int) $a);
            }
            $this->entries[$d] = $object ?? new CommitRef($c, (int) $a);
        }

        $this->initialized = true;
    }
}