function git_commitdiff($projectroot, $project, $hash, $hash_parent) { global $tpl; $cachekey = sha1($project) . "|" . $hash . "|" . $hash_parent; $git = new Git($projectroot . $project); $hash = sha1_bin($hash); if (isset($hash_parent)) { $hash_parent = sha1_bin($hash_parent); } if (!$tpl->is_cached('commitdiff.tpl', $cachekey)) { $co = git_read_commit($git, $hash); $ad = date_str($co['author_epoch']); $tpl->assign('committer', $co['committer']); $tpl->assign('rfc2822', $ad['rfc2822']); if (!isset($hash_parent) && isset($co['parent'])) { $hash_parent = sha1_bin($co['parent']); } $a_tree = isset($hash_parent) ? $git->getObject($hash_parent)->getTree() : array(); $b_tree = $git->getObject(sha1_bin($co['tree'])); $difftree = GitTree::diffTree($a_tree, $b_tree); $tpl->assign("hash", sha1_hex($hash)); $tpl->assign("tree", $co['tree']); $tpl->assign("hashparent", sha1_hex($hash_parent)); $tpl->assign("title", $co['title']); $refs = read_info_ref($git); if (isset($refs[$hash])) { $tpl->assign("commitref", $refs[$hash]); } $tpl->assign("comment", $co['comment']); $difftreelines = array(); $status_map = array(GitTree::TREEDIFF_ADDED => "A", GitTree::TREEDIFF_REMOVED => "D", GitTree::TREEDIFF_CHANGED => "M"); foreach ($difftree as $file => $diff) { $difftreeline = array(); $difftreeline["from_mode"] = decoct($diff->old_mode); $difftreeline["to_mode"] = decoct($diff->new_mode); $difftreeline["from_id"] = sha1_hex($diff->old_obj); $difftreeline["to_id"] = sha1_hex($diff->new_obj); $difftreeline["status"] = $status_map[$diff->status]; $difftreeline["file"] = $file; $difftreeline["md5"] = md5($file); $difftreeline["from_type"] = file_type($difftreeline["from_mode"]); $difftreeline["to_type"] = file_type($difftreeline["to_mode"]); if ($diff->status == GitTree::TREEDIFF_ADDED) { $difftreeline['diffout'] = explode("\n", git_diff($git, null, "/dev/null", $diff->new_obj, "b/" . $file)); } else { if ($diff->status == GitTree::TREEDIFF_REMOVED) { $difftreeline['diffout'] = explode("\n", git_diff($git, $diff->old_obj, "a/" . $file, null, "/dev/null")); } else { if ($diff->status == GitTree::TREEDIFF_CHANGED && $diff->old_obj != $diff->new_obj) { $difftreeline['diffout'] = explode("\n", git_diff($git, $diff->old_obj, "a/" . $file, $diff->new_obj, "b/" . $file)); } } } $difftreelines[] = $difftreeline; } $tpl->assign("difftreelines", $difftreelines); } $tpl->display('commitdiff.tpl', $cachekey); }
function git_commitdiff_plain($projectroot, $project, $hash, $hash_parent) { global $tpl; $cachekey = sha1($project) . "|" . $hash . "|" . $hash_parent; header("Content-type: text/plain; charset=UTF-8"); header("Content-disposition: inline; filename=\"git-" . $hash . ".patch\""); $git = new Git($projectroot . $project); $hash = sha1_bin($hash); if (isset($hash_parent)) { $hash_parent = sha1_bin($hash_parent); } if (!$tpl->is_cached('diff_plaintext.tpl', $cachekey)) { $co = git_read_commit($git, $hash); if (!isset($hash_parent) && isset($co['parent'])) { $hash_parent = sha1_bin($co['parent']); } $a_tree = isset($hash_parent) ? $git->getObject($hash_parent)->getTree() : array(); $b_tree = $git->getObject(sha1_bin($co['tree'])); $difftree = GitTree::diffTree($a_tree, $b_tree); // FIXME: simplified tagname search is not implemented yet /*$refs = read_info_ref($git,"tags"); $listout = git_read_revlist($git, "HEAD"); foreach ($listout as $i => $rev) { if (isset($refs[$rev])) $tagname = $refs[$rev]; if ($rev == $hash) break; }*/ $ad = date_str($co['author_epoch'], $co['author_tz']); $tpl->assign("from", $co['author']); $tpl->assign("date", $ad['rfc2822']); $tpl->assign("subject", $co['title']); if (isset($tagname)) { $tpl->assign("tagname", $tagname); } $tpl->assign("url", script_url() . "?p=" . $project . "&a=commitdiff&h=" . sha1_hex($hash)); $tpl->assign("comment", $co['comment']); $diffs = array(); foreach ($difftree as $file => $diff) { if ($diff->status == GitTree::TREEDIFF_ADDED) { $diffs[] = git_diff($git, null, "/dev/null", $diff->new_obj, "b/" . $file); } else { if ($diff->status == GitTree::TREEDIFF_REMOVED) { $diffs[] = git_diff($git, $diff->old_obj, "a/" . $file, null, "/dev/null"); } else { if ($diff->status == GitTree::TREEDIFF_CHANGED) { $diffs[] = git_diff($git, $diff->old_obj, "a/" . $file, $diff->new_obj, "b/" . $file); } } } } $tpl->assign("diffs", $diffs); } $tpl->display('diff_plaintext.tpl', $cachekey); }
function git_rss($projectroot, $project) { global $tpl; header("Content-type: text/xml; charset=UTF-8"); $cachekey = sha1($project); $git = new Git($projectroot . $project); if (!$tpl->is_cached('rss.tpl', $cachekey)) { $head = git_read_head($git); $revlist = git_read_revlist($git, $head, GITPHP_RSS_ITEMS); $tpl->assign("self", script_url()); $commitlines = array(); $revlistcount = count($revlist); for ($i = 0; $i < $revlistcount; ++$i) { $commit = $revlist[$i]; $co = git_read_commit($git, $commit->getName()); if ($i >= 20 && time() - $co['committer_epoch'] > 48 * 60 * 60) { break; } $cd = date_str($co['committer_epoch']); $difftree = array(); $diffout = GitTree::diffTree(isset($commit->parent[0]) ? $commit->parent[0]->getTree() : null, $commit->getTree()); foreach ($diffout as $file => $diff) { $difftree[] = $file; } $commitline = array(); $commitline["cdmday"] = $cd['mday']; $commitline["cdmonth"] = $cd['month']; $commitline["cdhour"] = $cd['hour']; $commitline["cdminute"] = $cd['minute']; $commitline["title"] = $co['title']; $commitline["author"] = $co['author']; $commitline["cdrfc2822"] = $cd['rfc2822']; $commitline["commit"] = $commit; $commitline["comment"] = $co['comment']; $commitline["difftree"] = $difftree; $commitlines[] = $commitline; } $tpl->assign("commitlines", $commitlines); } $tpl->display('rss.tpl', $cachekey); }
/** * Sets the path to object (implements the ArrayAccess interface). * * @param string $path * @param string $object * */ public function offsetSet($path, $object) { $path = new GitPath($path); if (!$object instanceof GitBlob) { throw new Exception('Object should be a GitBlob'); } if ($this->isReadOnly()) { throw new Exception('Can not write to locked object'); } if ($path->isRoot()) { throw new Exception('Can not set self to another object'); } if ($path->isSingle()) { $beSureDataIsLoaded = $this->nodes; $this->data['nodes'][$path[0]] = $object; } else { if (isset($this->nodes[$path[0]])) { $sub = $this->nodes[$path[0]]; if ($sub->isReadOnly()) { // clone the loaded object, to make it a new one $sub = clone $sub; } } else { $sub = new GitTree($this->git); } if (!$sub instanceof GitTree) { throw new Exception('Invalid path to set'); } $this->data['nodes'][$path[0]] = $sub; $sub->offsetSet($path->getShifted(), $object); } }
function git_commit($projectroot, $project, $hash) { global $tpl; $cachekey = sha1($project) . "|" . $hash; $git = new Git($projectroot . $project); $hash = $git->revParse($hash); if (!$tpl->is_cached('commit.tpl', $cachekey)) { $co = git_read_commit($git, $hash); $ad = date_str($co['author_epoch'], $co['author_tz']); $cd = date_str($co['committer_epoch'], $co['committer_tz']); if (isset($co['parent'])) { $a_tree = $git->getObject(sha1_bin($co['parent']))->getTree(); } else { $a_tree = false; } $b_tree = $git->getObject(sha1_bin($co['tree'])); $difftree = GitTree::diffTree($a_tree, $b_tree); ksort($difftree); $tpl->assign("hash", sha1_hex($hash)); $tpl->assign("tree", $co['tree']); if (isset($co['parent'])) { $tpl->assign("parent", $co['parent']); } $tpl->assign("title", $co['title']); $refs = read_info_ref($git); if (isset($refs[$hash])) { $tpl->assign("commitref", $refs[$hash]); } $tpl->assign("author", $co['author']); $tpl->assign("adrfc2822", $ad['rfc2822']); $tpl->assign("adhourlocal", $ad['hour_local']); $tpl->assign("adminutelocal", $ad['minute_local']); $tpl->assign("adtzlocal", $ad['tz_local']); $tpl->assign("committer", $co['committer']); $tpl->assign("cdrfc2822", $cd['rfc2822']); $tpl->assign("cdhourlocal", $cd['hour_local']); $tpl->assign("cdminutelocal", $cd['minute_local']); $tpl->assign("cdtzlocal", $cd['tz_local']); $tpl->assign("id", $co['id']); $tpl->assign("parents", $co['parents']); $tpl->assign("comment", $co['comment']); $tpl->assign("difftreesize", count($difftree) + 1); $status_map = array(GitTree::TREEDIFF_ADDED => "A", GitTree::TREEDIFF_REMOVED => "D", GitTree::TREEDIFF_CHANGED => "M"); $difftreelines = array(); foreach ($difftree as $file => $diff) { $difftreeline = array(); $difftreeline["from_mode"] = decoct($diff->old_mode); $difftreeline["to_mode"] = decoct($diff->new_mode); $difftreeline["from_mode_cut"] = substr(decoct($diff->old_mode), -4); $difftreeline["to_mode_cut"] = substr(decoct($diff->new_mode), -4); $difftreeline["from_id"] = sha1_hex($diff->old_obj); $difftreeline["to_id"] = sha1_hex($diff->new_obj); $difftreeline["status"] = $status_map[$diff->status]; $difftreeline["similarity"] = ""; $difftreeline["file"] = $file; $difftreeline["from_file"] = ""; $difftreeline["from_filetype"] = ""; $difftreeline["to_file"] = ""; $difftreeline["to_filetype"] = ""; $difftreeline["isreg"] = TRUE; $modestr = ""; /*if ((octdec($regs[1]) & 0x17000) != (octdec($regs[2]) & 0x17000)) $modestr .= " from " . file_type($regs[1]) . " to " . file_type($regs[2]); if ((octdec($regs[1]) & 0777) != (octdec($regs[2]) & 0777)) { if ((octdec($regs[1]) & 0x8000) && (octdec($regs[2]) & 0x8000)) $modestr .= " mode: " . (octdec($regs[1]) & 0777) . "->" . (octdec($regs[2]) & 0777); else if (octdec($regs[2]) & 0x8000) $modestr .= " mode: " . (octdec($regs[2]) & 0777);*/ $difftreeline["modechange"] = $modestr; $simmodechg = ""; /*if ($regs[1] != $regs[2]) $simmodechg .= ", mode: " . (octdec($regs[2]) & 0777);*/ $difftreeline["simmodechg"] = $simmodechg; $difftreelines[] = $difftreeline; } $tpl->assign("difftreelines", $difftreelines); } $tpl->display('commit.tpl', $cachekey); }
/** * @brief Updates a node in this tree. * * Missing directories in the path will be created automatically. * * @param $path (string) Path to the node, relative to this tree. * @param $mode Git mode to set the node to. 0 if the node shall be * cleared, i.e. the tree or blob shall be removed from this path. * @param $object (string) Binary SHA-1 hash of the object that shall be * placed at the given path. * * @returns (array of GitObject) An array of GitObject%s that were newly * created while updating the specified node. Those need to be written to * the repository together with the modified tree. */ public function updateNode($path, $mode, $object) { if (!is_array($path)) { $path = explode('/', $path); } $name = array_shift($path); if (count($path) == 0) { /* create leaf node */ if ($mode) { $node = new stdClass(); $node->mode = $mode; $node->name = $name; $node->object = $object; $node->is_dir = !!($mode & 040000); $this->nodes[$node->name] = $node; } else { unset($this->nodes[$name]); } return array(); } else { /* descend one level */ if (isset($this->nodes[$name])) { $node = $this->nodes[$name]; if (!$node->is_dir) { throw new GitTreeInvalidPathError(); } $subtree = clone $this->repo->getObject($node->object); } else { /* create new tree */ $subtree = new GitTree($this->repo); $node = new stdClass(); $node->mode = 040000; $node->name = $name; $node->is_dir = TRUE; $this->nodes[$node->name] = $node; } $pending = $subtree->updateNode($path, $mode, $object); $subtree->rehash(); $node->object = $subtree->getName(); $pending[] = $subtree; return $pending; } }
public static function treeDiff($a, $b) { return GitTree::treeDiff($a ? $a->getTree() : NULL, $b ? $b->getTree() : NULL); }
/** * 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; }