/** * Removes the node from the path recursively * * @param string $path */ public function offsetUnset($path) { $path = new GitPath($path); if ($this->isReadOnly()) { throw new Exception('Can not write to locked object'); } if (!$path->isSingle() && isset($this->nodes[$path[0]])) { $sub = $this->nodes[$path[0]]; if (!$sub instanceof GitTree) { throw new Exception('Invalid path'); } if ($sub->isReadOnly()) { $sub = clone $sub; $this->data['nodes'][$path[0]] = $sub; } $sub->offsetUnset($path->getShifted()); } if ($path->isRoot()) { throw new Exception('Can not unset self'); } if ($path->isSingle() || count($this->data['nodes'][$path[0]]) == 0) { unset($this->data['nodes'][$path[0]]); } }
/** * Returns the node associated with the supplied path (implements the ArrayAccess interface). * * @param string $index The path of the object to get * * @return GitBlob, GitTree */ public function offsetGet($path) { $path = new GitPath($path); $object = array_key_exists((string) $path, $this->stash) ? new GitBlob($this->git, null, null, $this->stash[(string) $path]) : $this->getTip()->offsetGet($path); if (is_null($object) || $object instanceof GitTree) { //make sure it's a cleaned reference, and that it's referencing a path $path = new GitPath($path . '/'); foreach (array_keys($this->stash) as $key) { $file = new GitPath($key); if ($file->hasAncestor($path)) { //remove $path part of the stash item $file->splice(0, count($path)); if (is_null($object)) { $object = new GitTree($this->git); } elseif ($object->isReadOnly()) { $object = clone $object; } if (is_null($this->stash[$key])) { unset($object[$file]); } else { $object[$file] = new GitBlob($this->git, null, null, $this->stash[$key]); } } } } return $object; }
$t->ok($p->refBlob(), 'no trailing slash references a blob object'); $p = new GitPath("abc/def/ghi/"); $t->ok($p->refTree(), 'a trailing slash references a tree object'); $t->comment('Testing array access'); $p = new GitPath("abc/def/ghi"); $t->is($p[0], 'abc', 'allows array access'); $t->is($p[-1], 'ghi', 'allows negative index array access'); $t->is(count($p), 3, 'count returns number of elements'); $t->comment('Testing iterator'); $p = new GitPath("abc/def"); foreach ($p as $index => $part) { switch ($index) { case 0: $t->is($part, 'abc', 'first iteration'); break; case 1: $t->is($part, 'def', 'second iteration'); break; } } $t->comment('Testing unset'); $p = new GitPath("abc/def/ghi/jkl"); unset($p[0]); $t->is((string) $p, "def/ghi/jkl", 'unset [0] removes first element'); unset($p[-1]); $t->is((string) $p, "def/ghi/", 'unset [-1] removes last element'); $t->comment('Ancestor check'); $child = new GitPath("abc/def/ghi"); $t->ok($child->hasAncestor(new GitPath('/')), 'Root is an ancestor of all'); $t->ok($child->hasAncestor(new GitPath('/abc/def/')), 'A directory can be an ancestor'); $t->ok(!$child->hasAncestor(new GitPath('/abc/def')), 'A blob path is never an ancestor');
public function hasAncestor(GitPath $path) { if ($path->refBlob() || count($path) >= $this->count()) { return false; } return count(array_intersect_assoc($this->parts, $path->getParts())) == count($path); }