Optimize the output of given branches

@param  array    &$branches Array of branches
@param  string    $which    Which end to optimize ("head" or "tail")
@return string[]            PHP expressions removed from the given part of the branches
550073
protected function optimizeBranchesOutput(array &$branches, $which)
	{
		$expressions = [];
		while (isset($branches[0][$which][0]))
		{
			$expr = $branches[0][$which][0];
			foreach ($branches as $branch)
			{
				if (!isset($branch[$which][0]) || $branch[$which][0] !== $expr)
				{
					break 2;
				}
			}

			$expressions[] = $expr;
			foreach ($branches as &$branch)
			{
				array_shift($branch[$which]);
			}
			unset($branch);
		}

		return $expressions;
	}
1181791
public static function getBOM(string $which)
    {
        $cname = self::class . '::' . strtoupper($which) . '_BOM';
        if (!defined($cname))
            return null;

        $bytes = constant($cname);
        $bom = '';
        foreach ($bytes as $ord)
            $bom .= chr($ord);
        return $bom;
    }
895042
public function getBranches()
    {
        static $cache = array();

        if (array_key_exists($this->path, $cache)) {
            return $cache[$this->path];
        }

        $branches = $this->getClient()->run($this, 'branch');
        $branches = explode("\n", $branches);
        $branches = array_filter(preg_replace('/[\*\s]/', '', $branches));

        if (empty($branches)) {
            return $cache[$this->path] = $branches;
        }

        // Since we've stripped whitespace, the result "* (detached from "
        // and "* (no branch)" that is displayed in detached HEAD state
        // becomes "(detachedfrom" and "(nobranch)" respectively.
        if ((0 === strpos($branches[0], '(detachedfrom')) || ('(nobranch)' === $branches[0])) {
            $branches = array_slice($branches, 1);
        }

        return $cache[$this->path] = $branches;
    }
323653
protected function analyseBranches()
	{
		$this->branches = [];
		foreach ($this->xpath->query('//xsl:apply-templates') as $applyTemplates)
		{
			$query            = 'ancestor::*[namespace-uri() != "' . self::XMLNS_XSL . '"]';
			$this->branches[] = iterator_to_array($this->xpath->query($query, $applyTemplates));
		}

		$this->computeAllowsChildElements();
		$this->computeAllowsText();
		$this->computeBitfields();
		$this->computeFormattingElement();
		$this->computeIsEmpty();
		$this->computeIsTransparent();
		$this->computeIsVoid();
		$this->computePreservesNewLines();
		$this->storeLeafNodes();
	}
684071
public static function getMatches(string $branchString)
    {
        $branchString = trim($branchString);

        $regexList = [
            '/^\*?\ *?(\S+)\ +(\S{40})\ +(.+)$/',
            '/^\*?\ *?\(.*(detached).*\)\ +(\S{40})\ +(.+)$/',
        ];

        $matches = [];
        while (empty($matches) and $regex = array_pop($regexList)) {
            preg_match($regex, trim($branchString), $matches);
        }

        if (empty($matches)) {
            throw new \InvalidArgumentException(sprintf('the branch string is not valid: %s', $branchString));
        }

        return array_map('trim', $matches);
    }
58015
public void setBranches(java.util.Collection<String> branches) {
        if (branches == null) {
            this.branches = null;
            return;
        }

        this.branches = new java.util.ArrayList<String>(branches);
    }
1205423
public function getBranch(string $name)
    {
        /** @var Branch $branch */
        foreach ($this->getBranches() as $branch) {
            if ($branch->getName() === $name) {
                return $branch;
            }
        }

        return null;
    }
369560
protected static function buildPHP(array $branches)
	{
		$return = ['', ''];
		foreach ($branches as $branch)
		{
			$return[0] .= $branch['statement'] . '{' . $branch['head'];
			$return[1] .= $branch['statement'] . '{';

			if ($branch['branches'])
			{
				list($head, $tail) = self::buildPHP($branch['branches']);

				$return[0] .= $head;
				$return[1] .= $tail;
			}

			$return[0] .= '}';
			$return[1] .= $branch['tail'] . '}';
		}

		return $return;
	}
97331
public static function cloneRelations($sources, $clones, $relations = [])
    {
        if (!is_array($sources)) {
            $sources = [$sources];
            $clones = [$clones];
        }
        foreach ($sources as $k => $source) {
            foreach ($relations as $j => $name) {
                list($name, $except) = is_array($name) ? [$j, $name] : [$name, ['id']];
                (new static($source, $name))->cloneRelation($clones[$k], $except);
            }
        }
    }
506804
public function getBranchTree($branch)
    {
        $hash = $this->getClient()->run($this, "log --pretty=\"%T\" --max-count=1 $branch");
        $hash = trim($hash, "\r\n ");

        return $hash ?: false;
    }
578395
public function getLastChild(Branch $branch = null)
    {
        if (null === $branch) {
            return null;
        }

        //end return last child or false if is not found
        $children = $branch->getChildren();
        $last = end($children);

        return $last ? $last : null;
    }
943655
public function getMainBranch()
    {
        $filtered = array_filter(
            $this->getBranches(),
            function (Branch $branch) {
                return $branch->getCurrent();
            }
        );
        sort($filtered);

        return $filtered[0];
    }
994667
public void setBranches(java.util.Collection<Branch> branches) {
        if (branches == null) {
            this.branches = null;
            return;
        }

        this.branches = new java.util.ArrayList<Branch>(branches);
    }
549367
public function enqueuePakoLibs(string $which = 'base')
    {
        if (($data = $this->didEnqueueLibs(__METHOD__))) {
            return $data; // Did this already.
        } // We only need to enqueue once.

        if ($which === 'base') {
            $data = [
                'scripts' => [
                    'pako' => [
                        'version' => '1.0.4',
                        'url'     => '//cdnjs.cloudflare.com/ajax/libs/pako/%1$s/pako.min.js',
                    ],
                ],
            ];
        } elseif ($which === 'deflate') {
            $data = [
                'scripts' => [
                    'pako-deflate' => [
                        'version' => '1.0.4',
                        'url'     => '//cdnjs.cloudflare.com/ajax/libs/pako/%1$s/pako_deflate.min.js',
                    ],
                ],
            ];
        } elseif ($which === 'inflate') {
            $data = [
                'scripts' => [
                    'pako-inflate' => [
                        'version' => '1.0.4',
                        'url'     => '//cdnjs.cloudflare.com/ajax/libs/pako/%1$s/pako_inflate.min.js',
                    ],
                ],
            ];
        }
        return $this->enqueueLibs(__METHOD__, $data);
    }
669158
protected function getSource($expr)
	{
		$php = 'switch(' . $expr . '){';
		foreach ($this->getValuesPerCodeBranch() as $branchCode => $values)
		{
			foreach ($values as $value)
			{
				$php .= 'case' . var_export((string) $value, true) . ':';
			}
			$php .= $branchCode . 'break;';
		}
		if ($this->defaultCode > '')
		{
			$php .= 'default:' . $this->defaultCode;
		}
		$php = preg_replace('(break;$)', '', $php) . '}';

		return $php;
	}
1217097
public static function optimize($operations)
    {
        $newOperations = [];
        /** @var $outOperation Operation */
        foreach ($operations as $outIndex => $outOperation) {
            $inOperations = array_slice($operations, $outIndex + 1);

            if ($inOperations) {
                foreach ($inOperations as $inIndex => $inOperation) {
                    // get how many items to fetch
                    $length = $inIndex;

                    $inBetween = array_slice($operations, $outIndex + 1, $length);

                    $result = $outOperation->reduce($inOperation, $inBetween);

                    if ($result) {
                        // add the result of the two merging
                        $newOperations = array_merge($newOperations, $result);
                        // add points that fell in between those that merged
                        $newOperations = array_merge($newOperations, $inBetween);
                        // add points that come after
                        $newOperations = array_merge(
                            $newOperations,
                            array_slice($operations, $outIndex + $inIndex + 2)
                        );

                        return $newOperations;
                    }
                }
                $newOperations[] = $outOperation;
            } else {
                $newOperations[] = $outOperation;
            }
        }

        return $newOperations;
    }
122142
public function add($data, $branch = null) {
		if (!is_null($branch)) $data = [$branch => $data];

		foreach ($data as $branch => $tree) {
			// first create the flat tree
			foreach ($tree as $path => $node) {
				// its ok just to pass a string as title
				if (is_string($node)) $node = ['title' => $node];

				if (!isset($node['title']) or empty($node['title'])) {
					throw new \Exception(__CLASS__ . "': You have to define a title for path '{$path}'.");
				}

				// add other information
				$node['active'] = false;

				$node['path']	= $path;
				$parts			= explode('/', $node['path']);
				$node['node']	= array_pop($parts);
				$node['parent']	= implode('_', $parts);

				// add to nodes collection
				$this->_nodes[$node['path']] = $node;

				// add to nested tree
				if (empty($node['parent'])) {
					$this->_tree[$branch][$path] =& $this->_nodes[$path];
				}
			}
		}

		$nodes =& $this->_nodes;

		// now create the references in between
		foreach ($nodes as $path => $node) {
			// add as child to parent
			if (isset($nodes[$node['parent']])) {
				$nodes[$node['parent']]['children'][$path] =& $nodes[$path];
			}
		}
	}