Create and use commit object
Create and use commit object

--- a/include/display.git_blame.php
+++ b/include/display.git_blame.php
@@ -7,20 +7,21 @@
  * Copyright (C) 2010 Christopher Han <xiphux@gmail.com>
  */
 
-require_once('gitutil.git_read_head.php');
 require_once('gitutil.git_parse_blame.php');
-require_once('gitutil.git_read_commit.php');
 require_once('gitutil.read_info_ref.php');
 require_once('gitutil.git_path_trees.php');
 
-function git_blame($projectroot, $project, $hash, $file, $hashbase)
+function git_blame($hash, $file, $hashbase)
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project) . "|" . sha1($file) . "|" . $hashbase;
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject()) . "|" . sha1($file) . "|" . $hashbase;
 
 	if (!$tpl->is_cached('blame.tpl', $cachekey)) {
-		$head = git_read_head();
+		$head = $gitphp_current_project->GetHeadCommit()->GetHash();
 		if (!isset($hashbase))
 			$hashbase = $head;
 		if (!isset($hash) && isset($file))
@@ -28,11 +29,12 @@
 		$tpl->assign("hash",$hash);
 		$tpl->assign("hashbase",$hashbase);
 		$tpl->assign("head", $head);
-		if ($co = git_read_commit($hashbase)) {
+		$co = $gitphp_current_project->GetCommit($hashbase);
+		if ($co) {
 			$tpl->assign("fullnav",TRUE);
 			$refs = read_info_ref();
-			$tpl->assign("tree",$co['tree']);
-			$tpl->assign("title",$co['title']);
+			$tpl->assign("tree",$co->GetTree()->GetHash());
+			$tpl->assign("title",$co->GetTitle());
 			if (isset($file))
 				$tpl->assign("file",$file);
 			if ($hashbase == "HEAD") {

--- a/include/display.git_blob.php
+++ b/include/display.git_blob.php
@@ -7,22 +7,23 @@
  *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
  */
 
- require_once('gitutil.git_read_head.php');
  require_once('gitutil.git_get_hash_by_path.php');
  require_once('gitutil.git_cat_file.php');
- require_once('gitutil.git_read_commit.php');
  require_once('gitutil.git_path_trees.php');
  require_once('gitutil.read_info_ref.php');
  require_once('util.file_mime.php');
 
-function git_blob($projectroot, $project, $hash, $file, $hashbase)
+function git_blob($hash, $file, $hashbase)
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project) . "|" . $hashbase . "|" . $hash . "|" . sha1($file);
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject()) . "|" . $hashbase . "|" . $hash . "|" . sha1($file);
 
 	if (!$tpl->is_cached('blob.tpl',$cachekey)) {
-		$head = git_read_head();
+		$head = $gitphp_current_project->GetHeadCommit()->GetHash();
 		if (!isset($hashbase))
 			$hashbase = $head;
 		if (!isset($hash) && isset($file))
@@ -31,11 +32,12 @@
 		$tpl->assign("hash",$hash);
 		$tpl->assign("hashbase",$hashbase);
 		$tpl->assign("head", $head);
-		if ($co = git_read_commit($hashbase)) {
+		$co = $gitphp_current_project->GetCommit($hashbase);
+		if ($co) {
 			$tpl->assign("fullnav",TRUE);
 			$refs = read_info_ref();
-			$tpl->assign("tree",$co['tree']);
-			$tpl->assign("title",$co['title']);
+			$tpl->assign("tree",$co->GetTree()->GetHash());
+			$tpl->assign("title",$co->GetTitle());
 			if (isset($file))
 				$tpl->assign("file",$file);
 			if ($hashbase == "HEAD") {

--- a/include/display.git_blobdiff.php
+++ b/include/display.git_blobdiff.php
@@ -8,16 +8,18 @@
  */
 
  require_once('util.prep_tmpdir.php');
- require_once('gitutil.git_read_commit.php');
  require_once('gitutil.read_info_ref.php');
  require_once('gitutil.git_path_trees.php');
  require_once('gitutil.git_diff.php');
 
-function git_blobdiff($projectroot,$project,$hash,$hashbase,$hashparent,$file)
+function git_blobdiff($hash,$hashbase,$hashparent,$file)
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project) . "|" . $hashbase . "|" . $hash . "|" . $hashparent . "|" . sha1($file);
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject()) . "|" . $hashbase . "|" . $hash . "|" . $hashparent . "|" . sha1($file);
 
 	if (!$tpl->is_cached('blobdiff.tpl', $cachekey)) {
 		$ret = prep_tmpdir();
@@ -30,10 +32,11 @@
 		$tpl->assign("hashbase",$hashbase);
 		if (isset($file))
 			$tpl->assign("file",$file);
-		if ($co = git_read_commit($hashbase)) {
+		$co = $gitphp_current_project->GetCommit($hashbase);
+		if ($co) {
 			$tpl->assign("fullnav",TRUE);
-			$tpl->assign("tree",$co['tree']);
-			$tpl->assign("title",$co['title']);
+			$tpl->assign("tree",$co->GetTree()->GetHash());
+			$tpl->assign("title",$co->GetTitle());
 			$refs = read_info_ref();
 			if (isset($refs[$hashbase]))
 				$tpl->assign("hashbaseref",$refs[$hashbase]);

--- a/include/display.git_commit.php
+++ b/include/display.git_commit.php
@@ -9,23 +9,26 @@
 
  require_once('util.file_type.php');
  require_once('util.date_str.php');
- require_once('gitutil.git_read_commit.php');
  require_once('gitutil.git_diff_tree.php');
  require_once('gitutil.read_info_ref.php');
 
-function git_commit($projectroot,$project,$hash)
+function git_commit($hash)
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project) . "|" . $hash;
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject()) . "|" . $hash;
 
 	if (!$tpl->is_cached('commit.tpl', $cachekey)) {
-		$co = git_read_commit($hash);
-		$ad = date_str($co['author_epoch'],$co['author_tz']);
-		$cd = date_str($co['committer_epoch'],$co['committer_tz']);
-		if (isset($co['parent'])) {
+		$commit = $gitphp_current_project->GetCommit($hash);
+		$ad = date_str($commit->GetAuthorEpoch(), $commit->GetAuthorTimezone());
+		$cd = date_str($commit->GetCommitterEpoch(), $commit->GetCommitterTimezone());
+		$parentObj = $commit->GetParent();
+		if ($parentObj) {
 			$root = "";
-			$parent = $co['parent'];
+			$parent = $parentObj->GetHash();
 		} else {
 			$root = "--root";
 			$parent = "";
@@ -33,26 +36,28 @@
 		$diffout = git_diff_tree($root . " " . $parent . " " . $hash, TRUE);
 		$difftree = explode("\n",$diffout);
 		$tpl->assign("hash",$hash);
-		$tpl->assign("tree",$co['tree']);
-		if (isset($co['parent']))
-			$tpl->assign("parent",$co['parent']);
-		$tpl->assign("title",$co['title']);
+		$treeObj = $commit->GetTree();
+		if ($treeObj)
+			$tpl->assign("tree", $treeObj->GetHash());
+		if ($parentObj)
+			$tpl->assign("parent", $parentObj->GetHash());
+		$tpl->assign("title", $commit->GetTitle());
 		$refs = read_info_ref();
-		if (isset($refs[$co['id']]))
-			$tpl->assign("commitref",$refs[$co['id']]);
-		$tpl->assign("author",$co['author']);
+		if (isset($refs[$commit->GetHash()]))
+			$tpl->assign("commitref",$refs[$commit->GetHash()]);
+		$tpl->assign("author", $commit->GetAuthorName());
 		$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("committer", $commit->GetCommitterName());
 		$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("id", $commit->GetHash());
+		$tpl->assign("parents", $commit->GetParents());
+		$tpl->assign("comment", $commit->GetComment());
 		$tpl->assign("difftreesize",count($difftree)+1);
 		$difftreelines = array();
 		foreach ($difftree as $i => $line) {

--- a/include/display.git_commitdiff.php
+++ b/include/display.git_commitdiff.php
@@ -9,16 +9,18 @@
 
  require_once('util.file_type.php');
  require_once('util.prep_tmpdir.php');
- require_once('gitutil.git_read_commit.php');
  require_once('gitutil.git_diff_tree.php');
  require_once('gitutil.read_info_ref.php');
  require_once('gitutil.git_diff.php');
 
-function git_commitdiff($projectroot,$project,$hash,$hash_parent)
+function git_commitdiff($hash,$hash_parent)
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project) . "|" . $hash . "|" . $hash_parent;
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject()) . "|" . $hash . "|" . $hash_parent;
 
 	if (!$tpl->is_cached('commitdiff.tpl', $cachekey)) {
 		$ret = prep_tmpdir();
@@ -26,19 +28,24 @@
 			echo $ret;
 			return;
 		}
-		$co = git_read_commit($hash);
-		if ((!isset($hash_parent)) && (isset($co['parent'])))
-			$hash_parent = $co['parent'];
+		$co = $gitphp_current_project->GetCommit($hash);
+		if (!isset($hash_parent)) {
+			$parent = $co->GetParent();
+			if ($parent)
+				$hash_parent = $parent->GetHash();
+		}
 		$diffout = git_diff_tree($hash_parent . " " . $hash);
 		$difftree = explode("\n",$diffout);
 		$refs = read_info_ref();
 		$tpl->assign("hash",$hash);
-		$tpl->assign("tree",$co['tree']);
+		$tree = $co->GetTree();
+		if ($tree)
+			$tpl->assign("tree", $tree->GetHash());
 		$tpl->assign("hashparent",$hash_parent);
-		$tpl->assign("title",$co['title']);
-		if (isset($refs[$co['id']]))
-			$tpl->assign("commitref",$refs[$co['id']]);
-		$tpl->assign("comment",$co['comment']);
+		$tpl->assign("title", $co->GetTitle());
+		if (isset($refs[$co->GetHash()]))
+			$tpl->assign("commitref",$refs[$co->GetHash()]);
+		$tpl->assign("comment",$co->GetComment());
 		$difftreelines = array();
 		foreach ($difftree as $i => $line) {
 			if (preg_match("/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/",$line,$regs)) {

--- a/include/display.git_commitdiff_plain.php
+++ b/include/display.git_commitdiff_plain.php
@@ -10,17 +10,19 @@
  require_once('util.prep_tmpdir.php');
  require_once('util.date_str.php');
  require_once('util.script_url.php');
- require_once('gitutil.git_read_commit.php');
  require_once('gitutil.git_diff_tree.php');
  require_once('gitutil.git_read_revlist.php');
  require_once('gitutil.read_info_ref.php');
  require_once('gitutil.git_diff.php');
 
-function git_commitdiff_plain($projectroot,$project,$hash,$hash_parent)
+function git_commitdiff_plain($hash,$hash_parent)
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project) . "|" . $hash . "|" . $hash_parent;
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject()) . "|" . $hash . "|" . $hash_parent;
 
 	header("Content-type: text/plain; charset=UTF-8");
 	header("Content-disposition: inline; filename=\"git-" . $hash . ".patch\"");
@@ -31,9 +33,12 @@
 			echo $ret;
 			return;
 		}
-		$co = git_read_commit($hash);
-		if (!isset($hash_parent))
-			$hash_parent = $co['parent'];
+		$co = $gitphp_current_project->GetCommit($hash);
+		if (!isset($hash_parent)) {
+			$parent = $co->GetParent();
+			if ($parent)
+				$hash_parent = $parent->GetHash();
+		}
 		$diffout = git_diff_tree($hash_parent . " " . $hash);
 		$difftree = explode("\n",$diffout);
 		$refs = read_info_ref('tags');
@@ -44,14 +49,14 @@
 			if ($rev == $hash)
 				break;
 		}
-		$ad = date_str($co['author_epoch'],$co['author_tz']);
-		$tpl->assign("from",$co['author']);
+		$ad = date_str($co->GetAuthorEpoch(), $co->GetAuthorTimezone());
+		$tpl->assign("from", $co->GetAuthor());
 		$tpl->assign("date",$ad['rfc2822']);
-		$tpl->assign("subject",$co['title']);
+		$tpl->assign("subject", $co->GetTitle());
 		if (isset($tagname))
 			$tpl->assign("tagname",$tagname);
-		$tpl->assign("url",script_url() . "?p=" . $project . "&a=commitdiff&h=" . $hash);
-		$tpl->assign("comment",$co['comment']);
+		$tpl->assign("url",script_url() . "?p=" . $gitphp_current_project->GetProject() . "&a=commitdiff&h=" . $hash);
+		$tpl->assign("comment", $co->GetComment());
 		$diffs = array();
 		foreach ($difftree as $i => $line) {
 			if (preg_match("/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/",$line,$regs)) {

--- a/include/display.git_heads.php
+++ b/include/display.git_heads.php
@@ -7,17 +7,19 @@
  *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
  */
 
- require_once('gitutil.git_read_head.php');
  require_once('gitutil.git_read_refs.php');
 
-function git_heads($projectroot,$project)
+function git_heads()
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project);
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject());
 
 	if (!$tpl->is_cached('heads.tpl', $cachekey)) {
-		$head = git_read_head();
+		$head = $gitphp_current_project->GetHeadCommit()->GetHash();
 		$tpl->assign("head",$head);
 		$headlist = git_read_refs("refs/heads");
 		$tpl->assign("headlist",$headlist);

--- a/include/display.git_history.php
+++ b/include/display.git_history.php
@@ -7,31 +7,35 @@
  *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
  */
 
+ require_once(GITPHP_INCLUDEDIR . 'defs.constants.php');
  require_once('gitutil.git_get_hash_by_path.php');
- require_once('gitutil.git_read_head.php');
- require_once('gitutil.git_read_commit.php');
  require_once('gitutil.read_info_ref.php');
  require_once('gitutil.git_history_list.php');
  require_once('gitutil.git_path_trees.php');
 
-function git_history($projectroot,$project,$hash,$file)
+function git_history($hash,$file)
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project) . "|" . $hash . "|" . sha1($file);
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject()) . "|" . $hash . "|" . sha1($file);
 
 	if (!$tpl->is_cached('history.tpl', $cachekey)) {
 		if (!isset($hash))
-			$hash = git_read_head();
-		$co = git_read_commit($hash);
+			$hash = $gitphp_current_project->GetHeadCommit()->GetHash();
+
+		$co = $gitphp_current_project->GetCommit($hash);
 		$refs = read_info_ref();
 		$tpl->assign("hash",$hash);
 		if (isset($refs[$hash]))
 			$tpl->assign("hashbaseref",$refs[$hash]);
-		$tpl->assign("tree",$co['tree']);
-		$tpl->assign("title",$co['title']);
+		$tpl->assign("tree", $co->GetTree()->GetHash());
+		$tpl->assign("title", $co->GetTitle());
 		$paths = git_path_trees($hash, $file);
 		$tpl->assign("paths",$paths);
+		date_default_timezone_set('UTC');
 		$cmdout = git_history_list($hash, $file);
 		$lines = explode("\n", $cmdout);
 		$historylines = array();
@@ -40,13 +44,19 @@
 				$commit = $regs[1];
 			else if (preg_match("/:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/",$line,$regs) && isset($commit)) {
 					$historyline = array();
-					$co = git_read_commit($commit);
-					$historyline["agestringage"] = $co['age_string_age'];
-					$historyline["agestringdate"] = $co['age_string_date'];
-					$historyline["authorname"] = $co['author_name'];
+					$co2 = $gitphp_current_project->GetCommit($commit);
+					$age = $co2->GetAge();
+					if ($age > 60*60*24*7*2) {
+						$historyline['agestringdate'] = date('Y-m-d', $co2->GetCommitterEpoch());
+						$historyline['agestringage'] = age_string($age);
+					} else {
+						$historyline['agestringdate'] = age_string($age);
+						$historyline['agestringage'] = date('Y-m-d', $co2->GetCommitterEpoch());
+					}
+					$historyline["authorname"] = $co2->GetAuthorName();
 					$historyline["commit"] = $commit;
 					$historyline["file"] = $file;
-					$historyline["title"] = $co['title_short'];
+					$historyline["title"] = $co2->GetTitle(GITPHP_TRIM_LENGTH);
 					if (isset($refs[$commit]))
 						$historyline["commitref"] = $refs[$commit];
 					$blob = git_get_hash_by_path($hash,$file);
@@ -56,6 +66,7 @@
 						$historyline["blobparent"] = $blob_parent;
 					}
 					$historylines[] = $historyline;
+					unset($co2);
 					unset($commit);
 			}
 		}

--- a/include/display.git_log.php
+++ b/include/display.git_log.php
@@ -8,19 +8,21 @@
  */
 
  require_once('util.date_str.php');
- require_once('gitutil.git_read_head.php');
+ require_once('util.age_string.php');
  require_once('gitutil.git_read_revlist.php');
- require_once('gitutil.git_read_commit.php');
  require_once('gitutil.read_info_ref.php');
 
-function git_log($projectroot,$project,$hash,$page)
+function git_log($hash,$page)
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project) . "|" . $hash . "|" . (isset($page) ? $page : 0);
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject()) . "|" . $hash . "|" . (isset($page) ? $page : 0);
 
 	if (!$tpl->is_cached('log.tpl', $cachekey)) {
-		$head = git_read_head();
+		$head = $gitphp_current_project->GetHeadCommit()->GetHash();
 		if (!isset($hash))
 			$hash = $head;
 		if (!isset($page))
@@ -39,8 +41,8 @@
 
 		if (!$revlist) {
 			$tpl->assign("norevlist",TRUE);
-			$co = git_read_commit($hash);
-			$tpl->assign("lastchange",$co['age_string']);
+			$co = $gitphp_current_project->GetCommit($hash);
+			$tpl->assign("lastchange", age_string($co->GetAge()));
 		}
 
 		$commitlines = array();
@@ -49,18 +51,19 @@
 			$commit = $revlist[$i];
 			if (isset($commit) && strlen($commit) > 1) {
 				$commitline = array();
-				$co = git_read_commit($commit);
-				$ad = date_str($co['author_epoch']);
-				$commitline["project"] = $project;
+				$co = $gitphp_current_project->GetCommit($commit);
+				$ad = date_str($co->GetAuthorEpoch());
+				$commitline["project"] = $gitphp_current_project->GetProject();
 				$commitline["commit"] = $commit;
 				if (isset($refs[$commit]))
 					$commitline["commitref"] = $refs[$commit];
-				$commitline["agestring"] = $co['age_string'];
-				$commitline["title"] = $co['title'];
-				$commitline["authorname"] = $co['author_name'];
+				$commitline["agestring"] = age_string($co->GetAge());
+				$commitline["title"] = $co->GetTitle();
+				$commitline["authorname"] = $co->GetAuthorName();
 				$commitline["rfc2822"] = $ad['rfc2822'];
-				$commitline["comment"] = $co['comment'];
+				$commitline["comment"] = $co->GetComment();
 				$commitlines[] = $commitline;
+				unset($co);
 			}
 		}
 		$tpl->assign("commitlines",$commitlines);

--- a/include/display.git_rss.php
+++ b/include/display.git_rss.php
@@ -10,45 +10,48 @@
  require_once('defs.constants.php');
  require_once('util.date_str.php');
  require_once('util.script_url.php');
- require_once('gitutil.git_read_head.php');
  require_once('gitutil.git_read_revlist.php');
- require_once('gitutil.git_read_commit.php');
  require_once('gitutil.git_diff_tree.php');
 
-function git_rss($projectroot,$project)
+function git_rss()
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
+
+	if (!$gitphp_current_project)
+		return;
+
 	header("Content-type: text/xml; charset=UTF-8");
 
-	$cachekey = sha1($project);
+	$cachekey = sha1($gitphp_current_project->GetProject());
 
 	if (!$tpl->is_cached('rss.tpl', $cachekey)) {
-		$head = git_read_head();
-		$revlist = git_read_revlist($head, GITPHP_RSS_ITEMS);
+		$head = $gitphp_current_project->GetHeadCommit();;
+		$revlist = git_read_revlist($head->GetHash(), 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($commit);
-			if (($i >= 20) && ((time() - $co['committer_epoch']) > 48*60*60))
+			$co = $gitphp_current_project->GetCommit($commit);
+			if (($i >= 20) && ((time() - $co->GetCommitterEpoch()) > 48*60*60))
 				break;
-			$cd = date_str($co['committer_epoch']);
+			$cd = date_str($co->GetCommitterEpoch());
 			$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["title"] = $co->GetTitle();
+			$commitline["author"] = $co->GetAuthor();
 			$commitline["cdrfc2822"] = $cd['rfc2822'];
 			$commitline["commit"] = $commit;
-			$commitline["comment"] = $co['comment'];
+			$commitline["comment"] = $co->GetComment();
 
-			if (isset($co['parent'])) {
+			$parent = $co->GetParent();
+			if ($parent) {
 				$difftree = array();
-				$diffout = git_diff_tree($co['parent'] . " " . $co['id']);
+				$diffout = git_diff_tree($parent->GetHash() . " " . $co->GetHash());
 				$tok = strtok($diffout,"\n");
 				while ($tok !== false) {
 					if (preg_match("/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/",$tok,$regs))
@@ -59,6 +62,7 @@
 			}
 
 			$commitlines[] = $commitline;
+			unset($co);
 		}
 		$tpl->assign("commitlines",$commitlines);
 	}

--- a/include/display.git_search.php
+++ b/include/display.git_search.php
@@ -8,16 +8,19 @@
  */
 
 require_once('defs.constants.php');
+require_once('util.age_string.php');
 require_once('util.highlight.php');
-require_once('gitutil.git_read_commit.php');
 require_once('gitutil.git_read_revlist.php');
 require_once('display.git_message.php');
 
-function git_search($projectroot, $project, $hash, $search, $searchtype, $page = 0)
+function git_search($hash, $search, $searchtype, $page = 0)
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
+	
+	if (!$gitphp_current_project)
+		return;
 
-	$cachekey = sha1($project) . "|" . $hash . "|" . sha1($searchtype) . "|" . sha1($search) . "|" . (isset($page) ? $page : 0);
+	$cachekey = sha1($gitphp_current_project->GetProject()) . "|" . $hash . "|" . sha1($searchtype) . "|" . sha1($search) . "|" . (isset($page) ? $page : 0);
 
 	if (!$tpl->is_cached('search.tpl', $cachekey)) {
 
@@ -31,11 +34,10 @@
 			return;
 		}
 		if (!isset($hash)) {
-			//$hash = git_read_head();
-			$hash = "HEAD";
+			$hash = 'HEAD';
 		}
 
-		$co = git_read_commit($hash);
+		$co = $gitphp_current_project->GetCommit($hash);
 
 		$revlist = git_read_revlist($hash, 101, ($page * 100), FALSE, FALSE, $searchtype, $search);
 		if (count($revlist) < 1 || (strlen($revlist[0]) < 1)) {
@@ -44,7 +46,7 @@
 		}
 
 		$tpl->assign("hash",$hash);
-		$tpl->assign("treehash",$co['tree']);
+		$tpl->assign("treehash", $co->GetTree()->GetHash());
 
 		$tpl->assign("search",$search);
 		$tpl->assign("searchtype",$searchtype);
@@ -52,31 +54,42 @@
 		$revlistcount = count($revlist);
 		$tpl->assign("revlistcount",$revlistcount);
 
-		$tpl->assign("title",$co['title']);
+		$tpl->assign("title", $co->GetTitle());
 
+		date_default_timezone_set('UTC');
 		$commitlines = array();
 		$commitcount = min(100,$revlistcount);
 		for ($i = 0; $i < $commitcount; ++$i) {
 			$commit = $revlist[$i];
 			if (strlen(trim($commit)) > 0) {
 				$commitline = array();
-				$co2 = git_read_commit($commit);
+				$co2 = $gitphp_current_project->GetCommit($commit);
 				$commitline["commit"] = $commit;
-				$commitline["agestringage"] = $co2['age_string_age'];
-				$commitline["agestringdate"] = $co2['age_string_date'];
-				$commitline["authorname"] = $co2['author_name'];
-				$commitline["title_short"] = $co2['title_short'];
-				if (strlen($co2['title_short']) < strlen($co2['title']))
-					$commitline["title"] = $co2['title'];
-				$commitline["committree"] = $co2['tree'];
+				$age = $co2->GetAge();
+				if ($age > 60*60*24*7*2) {
+					$commitline['agestringdate'] = date('Y-m-d', $co2->GetCommitterEpoch());
+					$commitline['agestringage'] = age_string($age);
+				} else {
+					$commitline['agestringdate'] = age_string($age);
+					$commitline['agestringage'] = date('Y-m-d', $co2->GetCommitterEpoch());
+				}
+				$commitline["authorname"] = $co2->GetAuthorName();
+				$title = $co2->GetTitle();
+				$titleshort = $co2->GetTitle(GITPHP_TRIM_LENGTH);
+				$commitline["title_short"] = $titleshort;
+				if (strlen($titleshort) < strlen($title))
+					$commitline["title"] = $title;
+				$commitline["committree"] = $co2->GetTree()->GetHash();
 				$matches = array();
-				foreach ($co2['comment'] as $comline) {
+				$commentlines = $co2->GetComment();
+				foreach ($commentlines as $comline) {
 					$hl = highlight($comline, $search, "searchmatch", GITPHP_TRIM_LENGTH);
 					if ($hl && (strlen($hl) > 0))
 						$matches[] = $hl;
 				}
 				$commitline["matches"] = $matches;
 				$commitlines[] = $commitline;
+				unset($co2);
 			}
 		}
 		

--- a/include/display.git_search_files.php
+++ b/include/display.git_search_files.php
@@ -10,14 +10,16 @@
 require_once('defs.constants.php');
 require_once('util.highlight.php');
 require_once('gitutil.git_filesearch.php');
-require_once('gitutil.git_read_commit.php');
 require_once('display.git_message.php');
 
-function git_search_files($projectroot, $project, $hash, $search, $page = 0)
+function git_search_files($hash, $search, $page = 0)
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project) . "|" . $hash . "|" . "filesearch" . "|" . sha1($search) . "|" . (isset($page) ? $page : 0);
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject()) . "|" . $hash . "|" . "filesearch" . "|" . sha1($search) . "|" . (isset($page) ? $page : 0);
 
 	if (!$tpl->is_cached('searchfiles.tpl', $cachekey)) {
 
@@ -31,11 +33,8 @@
 			return;
 		}
 		if (!isset($hash)) {
-			//$hash = git_read_head();
 			$hash = "HEAD";
 		}
-
-		$co = git_read_commit($hash);
 
 		$filesearch = git_filesearch($hash, $search, false, ($page * 100), 101);
 
@@ -45,7 +44,15 @@
 		}
 
 		$tpl->assign("hash",$hash);
-		$tpl->assign("treehash",$co['tree']);
+
+		$co = $gitphp_current_project->GetCommit($hash);
+
+		if ($co) {
+			$tree = $co->GetTree();
+			if ($tree)
+				$tpl->assign("treehash", $tree->GetHash());
+			$tpl->assign("title", $co->GetTitle());
+		}
 
 		$tpl->assign("search",$search);
 		$tpl->assign("searchtype","file");
@@ -53,7 +60,6 @@
 		$filesearchcount = count($filesearch);
 		$tpl->assign("filesearchcount",$filesearchcount);
 
-		$tpl->assign("title",$co['title']);
 
 		$filesearchlines = array();
 		$i = 0;

--- a/include/display.git_shortlog.php
+++ b/include/display.git_shortlog.php
@@ -7,27 +7,30 @@
  *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
  */
 
+ require_once('defs.constants.php');
  require_once('util.date_str.php');
- require_once('gitutil.git_read_head.php');
+ require_once('util.age_string.php');
  require_once('gitutil.git_read_revlist.php');
- require_once('gitutil.git_read_commit.php');
  require_once('gitutil.read_info_ref.php');
 
-function git_shortlog($projectroot,$project,$hash,$page)
+function git_shortlog($hash,$page)
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project) . "|" . $hash . "|" . (isset($page) ? $page : 0);
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject()) . "|" . $hash . "|" . (isset($page) ? $page : 0);
 
 	if (!$tpl->is_cached('shortlog.tpl', $cachekey)) {
-		$head = git_read_head();
+		$head = $gitphp_current_project->GetHeadCommit();;
 		if (!isset($hash))
-			$hash = $head;
+			$hash = $head->GetHash();
 		if (!isset($page))
 			$page = 0;
 		$refs = read_info_ref();
 		$tpl->assign("hash",$hash);
-		$tpl->assign("head",$head);
+		$tpl->assign("head",$head->GetHash());
 
 		if ($page)
 			$tpl->assign("page",$page);
@@ -45,16 +48,25 @@
 				$commitline = array();
 				if (isset($refs[$commit]))
 					$commitline["commitref"] = $refs[$commit];
-				$co = git_read_commit($commit);
-				$ad = date_str($co['author_epoch']);
+				$co = $gitphp_current_project->GetCommit($commit);
+				$ad = date_str($co->GetAuthorEpoch());
 				$commitline["commit"] = $commit;
-				$commitline["agestringage"] = $co['age_string_age'];
-				$commitline["agestringdate"] = $co['age_string_date'];
-				$commitline["authorname"] = $co['author_name'];
-				$commitline["title_short"] = $co['title_short'];
-				if (strlen($co['title_short']) < strlen($co['title']))
-					$commitline["title"] = $co['title'];
+				$age = $co->GetAge();
+				if ($age > 60*60*24*7*2) {
+					$commitline["agestringdate"] = date('Y-m-d', $co->GetCommitterEpoch());
+					$commitline["agestringage"] = age_string($age);
+				} else {
+					$commitline["agestringdate"] = age_string($age);
+					$commitline["agestringage"] = date('Y-m-d', $co->GetCommitterEpoch());
+				}
+				$commitline["authorname"] = $co->GetAuthorName();
+				$titleshort = $co->GetTitle(GITPHP_TRIM_LENGTH);
+				$title = $co->GetTitle();
+				$commitline["title_short"] = $titleshort;
+				if (strlen($titleshort) < strlen($title))
+					$commitline["title"] = $title;
 				$commitlines[] = $commitline;
+				unset($co);
 			}
 		}
 		$tpl->assign("commitlines",$commitlines);

--- a/include/display.git_summary.php
+++ b/include/display.git_summary.php
@@ -7,9 +7,9 @@
  *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
  */
 
+ require_once(GITPHP_INCLUDEDIR . 'defs.constants.php');
  require_once(GITPHP_INCLUDEDIR . 'util.date_str.php');
- require_once(GITPHP_INCLUDEDIR . 'gitutil.git_read_head.php');
- require_once(GITPHP_INCLUDEDIR . 'gitutil.git_read_commit.php');
+ require_once(GITPHP_INCLUDEDIR . 'util.age_string.php');
  require_once(GITPHP_INCLUDEDIR . 'gitutil.git_read_revlist.php');
  require_once(GITPHP_INCLUDEDIR . 'gitutil.git_read_refs.php');
  require_once(GITPHP_INCLUDEDIR . 'gitutil.read_info_ref.php');
@@ -22,42 +22,43 @@
 	if (!$gitphp_current_project)
 		return;
 
-	$project = $gitphp_current_project->GetProject();
-
-	$cachekey = sha1($project);
+	$cachekey = sha1($gitphp_current_project->GetProject());
 
 	if (!$tpl->is_cached('project.tpl', $cachekey)) {
 		$projectroot = GitPHP_Config::GetInstance()->GetValue('projectroot');
 
 		$descr = $gitphp_current_project->GetDescription();
-		$head = git_read_head();
-		$commit = git_read_commit($head);
-		$commitdate = date_str($commit['committer_epoch'],$commit['committer_tz']);
+		$headCommit = $gitphp_current_project->GetHeadCommit();
+		$commitdate = date_str($headCommit->GetCommitterEpoch(), $headCommit->GetCommitterTimezone());
 		$owner = $gitphp_current_project->GetOwner();
 		$refs = read_info_ref();
-		$tpl->assign("head",$head);
+		$tpl->assign("head", $headCommit->GetHash());
 		$tpl->assign("description",$descr);
 		$tpl->assign("owner",$owner);
 		$tpl->assign("lastchange",$commitdate['rfc2822']);
 		if (GitPHP_Config::GetInstance()->HasKey('cloneurl'))
-			$tpl->assign('cloneurl', GitPHP_Config::GetInstance()->GetValue('cloneurl') . $project);
+			$tpl->assign('cloneurl', GitPHP_Config::GetInstance()->GetValue('cloneurl') . $gitphp_current_project->GetProject());
 		if (GitPHP_Config::GetInstance()->HasKey('pushurl'))
-			$tpl->assign('pushurl', GitPHP_Config::GetInstance()->GetValue('pushurl') . $project);
-		$revlist = git_read_revlist($head, 17);
+			$tpl->assign('pushurl', GitPHP_Config::GetInstance()->GetValue('pushurl') . $gitphp_current_project->GetProject());
+		$revlist = git_read_revlist($headCommit->GetHash(), 17);
 		foreach ($revlist as $i => $rev) {
 			$revdata = array();
-			$revco = git_read_commit($rev);
-			$authordate = date_str($revco['author_epoch']);
 			$revdata["commit"] = $rev;
 			if (isset($refs[$rev]))
 				$revdata["commitref"] = $refs[$rev];
-			$revdata["commitage"] = $revco['age_string'];
-			$revdata["commitauthor"] = $revco['author_name'];
-			if (strlen($revco['title_short']) < strlen($revco['title'])) {
-				$revdata["title"] = $revco['title'];
-				$revdata["title_short"] = $revco['title_short'];
-			} else
-				$revdata["title_short"] = $revco['title'];
+			$revco = $gitphp_current_project->GetCommit($rev);
+			if ($revco) {
+				$revdata["commitage"] = age_string($revco->GetAge());
+				$revdata["commitauthor"] = $revco->GetAuthorName();
+				$title = $revco->GetTitle();
+				$title_short = $revco->GetTitle(GITPHP_TRIM_LENGTH);
+				if (strlen($title_short) < strlen($title)) {
+					$revdata["title"] = $title;
+					$revdata["title_short"] = $title_short;
+				} else
+					$revdata["title_short"] = $title;
+				unset($revco);
+			}
 			$revlist[$i] = $revdata;
 		}
 		$tpl->assign("revlist",$revlist);

--- a/include/display.git_tag.php
+++ b/include/display.git_tag.php
@@ -9,17 +9,19 @@
 
  require_once('util.date_str.php');
  require_once('gitutil.git_read_tag.php');
- require_once('gitutil.git_read_head.php');
 
-function git_tag($projectroot, $project, $hash)
+function git_tag($hash)
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project) . "|" . $hash;
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject()) . "|" . $hash;
 
 	if (!$tpl->is_cached('tag.tpl', $cachekey)) {
 
-		$head = git_read_head();
+		$head = $gitphp_current_project->GetHeadCommit()->GetHash();
 		$tpl->assign("head",$head);
 		$tpl->assign("hash", $hash);
 

--- a/include/display.git_tags.php
+++ b/include/display.git_tags.php
@@ -7,17 +7,19 @@
  *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
  */
 
- require_once('gitutil.git_read_head.php');
  require_once('gitutil.git_read_refs.php');
 
-function git_tags($projectroot,$project)
+function git_tags()
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project);
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject());
 
 	if (!$tpl->is_cached('tags.tpl', $cachekey)) {
-		$head = git_read_head();
+		$head = $gitphp_current_project->GetHeadCommit()->GetHash();
 		$tpl->assign("head",$head);
 		$taglist = git_read_refs("refs/tags");
 		if (isset($taglist) && (count($taglist) > 0)) {

--- a/include/display.git_tree.php
+++ b/include/display.git_tree.php
@@ -8,38 +8,42 @@
  */
 
  require_once('util.mode_str.php');
- require_once('gitutil.git_read_head.php');
  require_once('gitutil.git_get_hash_by_path.php');
  require_once('gitutil.git_ls_tree.php');
  require_once('gitutil.read_info_ref.php');
- require_once('gitutil.git_read_commit.php');
  require_once('gitutil.git_path_trees.php');
 
-function git_tree($projectroot,$project,$hash,$file,$hashbase)
+function git_tree($hash,$file,$hashbase)
 {
-	global $tpl;
+	global $tpl, $gitphp_current_project;
 
-	$cachekey = sha1($project) . "|" . $hashbase . "|" . $hash . "|" . sha1($file);
+	if (!$gitphp_current_project)
+		return;
+
+	$cachekey = sha1($gitphp_current_project->GetProject()) . "|" . $hashbase . "|" . $hash . "|" . sha1($file);
 
 	if (!$tpl->is_cached('tree.tpl', $cachekey)) {
+		
 		if (!isset($hash)) {
-			$hash = git_read_head();
+			$hash = $gitphp_current_project->GetHeadCommit()->GetHash();
 			if (isset($file))
 				$hash = git_get_hash_by_path(($hashbase?$hashbase:$hash),$file,"tree");
-				if (!isset($hashbase))
-					$hashbase = $hash;
 		}
+		if (!isset($hashbase))
+			$hashbase = $hash;
 		$lsout = git_ls_tree($hash, TRUE);
 		$refs = read_info_ref();
 		$tpl->assign("hash",$hash);
 		if (isset($hashbase))
 			$tpl->assign("hashbase",$hashbase);
-		if (isset($hashbase) && ($co = git_read_commit($hashbase))) {
-			$basekey = $hashbase;
-			$tpl->assign("fullnav",TRUE);
-			$tpl->assign("title",$co['title']);
-			if (isset($refs[$hashbase]))
-				$tpl->assign("hashbaseref",$refs[$hashbase]);
+		if (isset($hashbase)) {
+			$co = $gitphp_current_project->GetCommit($hashbase);
+			if ($co) {
+				$tpl->assign("fullnav",TRUE);
+				$tpl->assign("title",$co->GetTitle());
+				if (isset($refs[$hashbase]))
+					$tpl->assign("hashbaseref",$refs[$hashbase]);
+			}
 		}
 		$paths = git_path_trees($hashbase, $file);
 		$tpl->assign("paths",$paths);

--- /dev/null
+++ b/include/git/Commit.class.php
@@ -1,1 +1,447 @@
-
+<?php
+/**
+ * GitPHP Commit
+ *
+ * Represents a single commit
+ *
+ * @author Christopher Han <xiphux@gmail.com>
+ * @copyright Copyright (c) 2010 Christopher Han
+ * @package GitPHP
+ * @subpackage Git
+ */
+
+require_once(GITPHP_INCLUDEDIR . 'defs.commands.php');
+require_once(GITPHP_INCLUDEDIR . 'git/GitObject.class.php');
+require_once(GITPHP_INCLUDEDIR . 'git/Tree.class.php');
+
+/**
+ * Commit class
+ *
+ * @package GitPHP
+ * @subpackage Git
+ */
+class GitPHP_Commit extends GitPHP_GitObject
+{
+
+	/**
+	 * dataRead
+	 *
+	 * Indicates whether data for this commit has been read
+	 *
+	 * @access protected
+	 */
+	protected $dataRead = false;
+
+	/**
+	 * parents
+	 *
+	 * Array of parent commits
+	 *
+	 * @access protected
+	 */
+	protected $parents = array();
+
+	/**
+	 * tree
+	 *
+	 * Tree object for this commit
+	 *
+	 * @access protected
+	 */
+	protected $tree;
+
+	/**
+	 * author
+	 *
+	 * Author for this commit
+	 *
+	 * @access protected
+	 */
+	protected $author;
+
+	/**
+	 * authorEpoch
+	 *
+	 * Author's epoch
+	 *
+	 * @access protected
+	 */
+	protected $authorEpoch;
+
+	/**
+	 * authorTimezone
+	 *
+	 * Author's timezone
+	 *
+	 * @access protected
+	 */
+	protected $authorTimezone;
+
+	/**
+	 * committer
+	 *
+	 * Committer for this commit
+	 *
+	 * @access protected
+	 */
+	protected $committer;
+
+	/**
+	 * committerEpoch
+	 *
+	 * Committer's epoch
+	 *
+	 * @access protected
+	 */
+	protected $committerEpoch;
+
+	/**
+	 * committerTimezone
+	 *
+	 * Committer's timezone
+	 *
+	 * @access protected
+	 */
+	protected $committerTimezone;
+
+	/**
+	 * title
+	 *
+	 * Stores the commit title
+	 *
+	 * @access protected
+	 */
+	protected $title;
+
+	/**
+	 * comment
+	 *
+	 * Stores the commit comment
+	 *
+	 * @access protected
+	 */
+	protected $comment = array();
+
+	/**
+	 * __construct
+	 *
+	 * Instantiates object
+	 *
+	 * @access public
+	 * @param mixed $project the project
+	 * @param string $hash object hash
+	 * @return mixed git object
+	 * @throws Exception exception on invalid hash
+	 */
+	public function __construct($project, $hash)
+	{
+		parent::__construct($project, $hash);
+	}
+
+	/**
+	 * GetParent
+	 *
+	 * Gets the main parent of this commit
+	 *
+	 * @access public
+	 * @return mixed commit object for parent
+	 */
+	public function GetParent()
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+
+		if (isset($this->parents[0]))
+			return $this->parents[0];
+		return null;
+	}
+
+	/**
+	 * GetParents
+	 *
+	 * Gets an array of parent objects for this commit
+	 *
+	 * @access public
+	 * @return mixed array of commit objects
+	 */
+	public function GetParents()
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+
+		return $this->parents;
+	}
+
+	/**
+	 * GetTree
+	 *
+	 * Gets the tree for this commit
+	 *
+	 * @access public
+	 * @return mixed tree object
+	 */
+	public function GetTree()
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+
+		return $this->tree;
+	}
+
+	/**
+	 * GetAuthor
+	 *
+	 * Gets the author for this commit
+	 *
+	 * @access public
+	 * @return string author
+	 */
+	public function GetAuthor()
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+
+		return $this->author;
+	}
+
+	/**
+	 * GetAuthorName
+	 *
+	 * Gets the author's name only
+	 *
+	 * @access public
+	 * @return string author name
+	 */
+	public function GetAuthorName()
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+
+		return preg_replace('/ <.*/', '', $this->author);
+	}
+
+	/**
+	 * GetAuthorEpoch
+	 *
+	 * Gets the author's epoch
+	 *
+	 * @access public
+	 * @return string author epoch
+	 */
+	public function GetAuthorEpoch()
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+
+		return $this->authorEpoch;
+	}
+
+	/**
+	 * GetAuthorTimezone
+	 *
+	 * Gets the author's timezone
+	 *
+	 * @access public
+	 * @return string author timezone
+	 */
+	public function GetAuthorTimezone()
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+
+		return $this->authorTimezone;
+	}
+
+	/**
+	 * GetCommitter
+	 *
+	 * Gets the author for this commit
+	 *
+	 * @access public
+	 * @return string author
+	 */
+	public function GetCommitter()
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+
+		return $this->committer;
+	}
+
+	/**
+	 * GetCommitterName
+	 *
+	 * Gets the author's name only
+	 *
+	 * @access public
+	 * @return string author name
+	 */
+	public function GetCommitterName()
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+
+		return preg_replace('/ <.*/', '', $this->committer);
+	}
+
+	/**
+	 * GetCommitterEpoch
+	 *
+	 * Gets the author's epoch
+	 *
+	 * @access public
+	 * @return string author epoch
+	 */
+	public function GetCommitterEpoch()
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+
+		return $this->committerEpoch;
+	}
+
+	/**
+	 * GetCommitterTimezone
+	 *
+	 * Gets the author's timezone
+	 *
+	 * @access public
+	 * @return string author timezone
+	 */
+	public function GetCommitterTimezone()
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+
+		return $this->committerTimezone;
+	}
+
+	/**
+	 * GetTitle
+	 *
+	 * Gets the commit title
+	 *
+	 * @access public
+	 * @param integer $trim length to trim to (0 for no trim)
+	 * @return string title
+	 */
+	public function GetTitle($trim = 0)
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+		
+		if (($trim > 0) && (strlen($this->title) > $trim)) {
+			return substr($this->title, 0, $trim) . '...';
+		}
+
+		return $this->title;
+	}
+
+	/**
+	 * GetComment
+	 *
+	 * Gets the lines of comment
+	 *
+	 * @access public
+	 * @return array lines of comment
+	 */
+	public function GetComment()
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+
+		return $this->comment;
+	}
+
+	/**
+	 * GetAge
+	 *
+	 * Gets the age of the commit
+	 *
+	 * @access public
+	 * @return string age
+	 */
+	public function GetAge()
+	{
+		if (!$this->dataRead)
+			$this->ReadData();
+
+		if (!empty($this->committerEpoch))
+			return time() - $this->committerEpoch;
+		
+		return '';
+	}
+
+	/**
+	 * ReadData
+	 *
+	 * Read the data for the commit
+	 *
+	 * @access protected
+	 */
+	protected function ReadData()
+	{
+		$this->dataRead = true;
+
+		/* get data from git_rev_list */
+		$exe = new GitPHP_GitExe(GitPHP_Config::GetInstance()->GetValue('gitbin'), $this->project);
+		$args = array();
+		$args[] = '--header';
+		$args[] = '--parents';
+		$args[] = '--max-count=1';
+		$args[] = $this->hash;
+		$ret = $exe->Execute(GIT_REV_LIST, $args);
+		unset($exe);
+
+		$lines = explode("\n", $ret);
+
+		if (!isset($lines[0]))
+			return;
+
+		/* In case we returned something unexpected */
+		$tok = strtok($lines[0], ' ');
+		if ($tok != $this->hash)
+			return;
+
+		/* Read all parents */
+		$tok = strtok(' ');
+		while ($tok !== false) {
+			try {
+				$this->parents[] = new GitPHP_Commit($this->project, $tok);
+			} catch (Exception $e) {
+			}
+			$tok = strtok(' ');
+		}
+
+		foreach ($lines as $i => $line) {
+			if (preg_match('/^tree ([0-9a-fA-F]{40})$/', $line, $regs)) {
+				/* Tree */
+				try {
+					$this->tree = new GitPHP_Tree($this->project, $regs[1]);
+				} catch (Exception $e) {
+				}
+			} else if (preg_match('/^author (.*) ([0-9]+) (.*)$/', $line, $regs)) {
+				/* author data */
+				$this->author = $regs[1];
+				$this->authorEpoch = $regs[2];
+				$this->authorTimezone = $regs[3];
+			} else if (preg_match('/^committer (.*) ([0-9]+) (.*)$/', $line, $regs)) {
+				/* committer data */
+				$this->committer = $regs[1];
+				$this->committerEpoch = $regs[2];
+				$this->committerTimezone = $regs[3];
+			} else {
+				/* commit comment */
+				if (!(preg_match('/^[0-9a-fA-F]{40}/', $line) || preg_match('/^parent [0-9a-fA-F]{40}/', $line))) {
+					$trimmed = trim($line);
+					if (empty($this->title) && (strlen($trimmed) > 0))
+						$this->title = $trimmed;
+					if (!empty($this->title))
+						$this->comment[] = $trimmed;
+				}
+			}
+		}
+	}
+
+}
+

--- /dev/null
+++ b/include/git/GitObject.class.php
@@ -1,1 +1,101 @@
+<?php
+/**
+ * GitPHP GitObject
+ *
+ * Base class for all hash objects in a git repository
+ *
+ * @author Christopher Han <xiphux@gmail.com>
+ * @copyright Copyright (c) 2010 Christopher Han
+ * @package GitPHP
+ * @subpackage Git
+ */
 
+/**
+ * Git Object class
+ *
+ * @abstract
+ * @package GitPHP
+ * @subpackage Git
+ */
+abstract class GitPHP_GitObject
+{
+	/**
+	 * project
+	 *
+	 * Stores the project internally
+	 *
+	 * @access protected
+	 */
+	protected $project;
+
+	/**
+	 * hash
+	 *
+	 * Stores the hash of the object internally
+	 *
+	 * @access protected
+	 */
+	protected $hash;
+
+	/**
+	 * __construct
+	 *
+	 * Instantiates object
+	 *
+	 * @access public
+	 * @param mixed $project the project
+	 * @param string $hash object hash
+	 * @return mixed git object
+	 * @throws Exception exception on invalid hash
+	 */
+	public function __construct($project, $hash)
+	{
+		$this->project = $project;
+		$this->SetHash($hash);
+	}
+
+	/**
+	 * GetProject
+	 *
+	 * Gets the project
+	 *
+	 * @access public
+	 * @return mixed project
+	 */
+	public function GetProject()
+	{
+		return $this->project;
+	}
+
+	/**
+	 * GetHash
+	 *
+	 * Gets the hash
+	 *
+	 * @access public
+	 * @return string object hash
+	 */
+	public function GetHash()
+	{
+		return $this->hash;
+	}
+
+	/**
+	 * SetHash
+	 *
+	 * Attempts to set the hash of this object
+	 *
+	 * @param string $hash the hash to set
+	 * @throws Exception on invalid hash
+	 * @access protected
+	 */
+	protected function SetHash($hash)
+	{
+		if (!(preg_match('/[0-9a-f]{40}/i', $hash))) {
+			throw new Exception('Invalid hash ' . $hash);
+		}
+		$this->hash = $hash;
+	}
+
+}
+

--- a/include/git/Project.class.php
+++ b/include/git/Project.class.php
@@ -10,7 +10,8 @@
  * @subpackage Git
  */
 
-require_once(GITPHP_INCLUDEDIR . 'defs.constants.php');
+require_once(GITPHP_INCLUDEDIR . 'defs.commands.php');
+require_once(GITPHP_INCLUDEDIR . 'git/Commit.class.php');
 
 /**
  * Project class
@@ -74,7 +75,35 @@
 	 *
 	 * @access protected
 	 */
-	protected $category = "";
+	protected $category = '';
+
+	/**
+	 * head
+	 *
+	 * Stores the head hash internally
+	 *
+	 * @access protected
+	 */
+	protected $head;
+
+	/**
+	 * readHead
+	 *
+	 * Stores whether the head ref has been read yet
+	 *
+	 * @access protected
+	 */
+	protected $readHead;
+
+	/**
+	 * commitCache
+	 *
+	 * Caches fetched commit objects in case of
+	 * repeated requests for the same object
+	 *
+	 * @access protected
+	 */
+	protected $commitCache = array();
 
 	/**
 	 * __construct
@@ -192,32 +221,20 @@
 	 * Gets the project description
 	 *
 	 * @access public
-	 * @param $trim true to trim the description length
+	 * @param $trim length to trim description to (0 for no trim)
 	 * @return string project description
 	 */
-	public function GetDescription($trim = false)
+	public function GetDescription($trim = 0)
 	{
 		if (!$this->readDescription) {
 			$this->description = file_get_contents($this->GetPath() . '/description');
 		}
-
-		if ((!$trim) || (strlen($this->description) < GITPHP_TRIM_LENGTH)) {
-			return $this->description;
-		}
-
-		return substr($this->description, 0, GITPHP_TRIM_LENGTH) . '...';
-	}
-
-	/**
-	 * GetAge
-	 *
-	 * Gets the project's age (last change time)
-	 *
-	 * @access public
-	 * @return mixed date
-	 */
-	public function GetAge()
-	{
+		
+		if (($trim > 0) && (strlen($this->description) > $trim)) {
+			return substr($this->description, 0, $trim) . '...';
+		}
+
+		return $this->description;
 	}
 
 	/**
@@ -246,5 +263,61 @@
 		$this->category = $category;
 	}
 
+	/**
+	 * GetHeadCommit
+	 *
+	 * Gets the head commit for this project
+	 * Shortcut for getting the tip commit of the HEAD branch
+	 *
+	 * @access public
+	 * @return mixed head commit
+	 */
+	public function GetHeadCommit()
+	{
+		if (!$this->readHead)
+			$this->ReadHeadCommit();
+
+		return $this->GetCommit($this->head);
+	}
+
+	/**
+	 * ReadHeadCommit
+	 *
+	 * Reads the head commit hash
+	 *
+	 * @access protected
+	 */
+	public function ReadHeadCommit()
+	{
+		$this->readHead = true;
+
+		$exe = new GitPHP_GitExe(GitPHP_Config::GetInstance()->GetValue('gitbin'), $this);
+		$args = array();
+		$args[] = '--verify';
+		$args[] = 'HEAD';
+		$this->head = trim($exe->Execute(GIT_REV_PARSE, $args));
+	}
+
+	/**
+	 * GetCommit
+	 *
+	 * Get a commit for this project
+	 *
+	 * @access public
+	 */
+	public function GetCommit($hash)
+	{
+		if (empty($hash))
+			return null;
+
+		if ($hash === 'HEAD')
+			return $this->GetHeadCommit();
+
+		if (!isset($this->commitCache[$hash]))
+			$this->commitCache[$hash] = new GitPHP_Commit($this, $hash);
+
+		return $this->commitCache[$hash];
+	}
+
 }
 

--- /dev/null
+++ b/include/git/Tree.class.php
@@ -1,1 +1,24 @@
+<?php
+/**
+ * GitPHP Tree
+ *
+ * Represents a single tree
+ *
+ * @author Christopher Han <xiphux@gmail.com>
+ * @copyright Copyright (c) 2010 Christopher Han
+ * @package GitPHP
+ * @subpackge Git
+ */
 
+require_once(GITPHP_INCLUDEDIR . 'git/GitObject.class.php');
+
+/**
+ * Tree class
+ *
+ * @package GitPHP
+ * @subpackage Git
+ */
+class GitPHP_Tree extends GitPHP_GitObject
+{
+}
+

--- a/include/gitutil.git_project_info.php
+++ b/include/gitutil.git_project_info.php
@@ -7,21 +7,22 @@
  *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
  */
 
- require_once(GITPHP_INCLUDEDIR . 'gitutil.git_read_head.php');
- require_once(GITPHP_INCLUDEDIR . 'gitutil.git_read_commit.php');
+ require_once(GITPHP_INCLUDEDIR . 'defs.constants.php');
+ require_once(GITPHP_INCLUDEDIR . 'util.age_string.php');
 
-function git_project_info($projectroot,$project)
+function git_project_info($project)
 {
 	$projectObj = GitPHP_ProjectList::GetInstance()->GetProject($project);
 
 	$projinfo = array();
-	$projinfo["project"] = $project;
-	$projinfo["descr"] = $projectObj->GetDescription(true);
-	$projinfo["owner"] = $projectObj->GetOwner();
-	$head = git_read_head();
-	$commit = git_read_commit($head);
-	$projinfo["age"] = $commit['age'];
-	$projinfo["age_string"] = $commit['age_string'];
+	$projinfo['project'] = $project;
+	$projinfo['descr'] = $projectObj->GetDescription(GITPHP_TRIM_LENGTH);
+	$projinfo['owner'] = $projectObj->GetOwner();
+	$commit = $projectObj->GetHeadCommit();
+	if ($commit) {
+		$projinfo['age'] = $commit->GetAge();
+		$projinfo['age_string'] = age_string($projinfo['age']);
+	}
 	return $projinfo;
 }
 

--- a/include/gitutil.git_read_commit.php
+++ /dev/null
@@ -1,79 +1,1 @@
-<?php
-/*
- *  gitutil.git_read_commit.php
- *  gitphp: A PHP git repository browser
- *  Component: Git utility - read a commit
- *
- *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
- */
 
- require_once('defs.constants.php');
- require_once('util.age_string.php');
- require_once('gitutil.git_read_revlist.php');
-
-function git_read_commit($head)
-{
-	$lines = git_read_revlist($head,1,NULL,TRUE,TRUE);
-	if (!($lines[0]) || !preg_match("/^[0-9a-fA-F]{40}/",$lines[0]))
-		return null;
-	$commit = array();
-	$tok = strtok($lines[0]," ");
-	$commit['id'] = $tok;
-	$tok = strtok(" ");
-	$parents = array();
-	while ($tok !== false) {
-		$parents[] = $tok;
-		$tok = strtok(" ");
-	}
-	$commit['parents'] = $parents;
-	if (isset($parents[0]))
-		$commit['parent'] = $parents[0];
-	$comment = array();
-	foreach ($lines as $i => $line) {
-		if (preg_match("/^tree ([0-9a-fA-F]{40})$/",$line,$regs))
-			$commit['tree'] = $regs[1];
-		else if (preg_match("/^author (.*) ([0-9]+) (.*)$/",$line,$regs)) {
-			$commit['author'] = $regs[1];
-			$commit['author_epoch'] = $regs[2];
-			$commit['author_tz'] = $regs[3];
-			if (preg_match("/^([^<]+) </",$commit['author'],$r))
-				$commit['author_name'] = $r[1];
-			else
-				$commit['author_name'] = $commit['author'];
-		} else if (preg_match("/^committer (.*) ([0-9]+) (.*)$/",$line,$regs)) {
-			$commit['committer'] = $regs[1];
-			$commit['committer_epoch'] = $regs[2];
-			$commit['committer_tz'] = $regs[3];
-			$commit['committer_name'] = $commit['committer'];
-			$commit['committer_name'] = preg_replace("/ <.*/","",$commit['committer_name']);
-		} else {
-			$trimmed = trim($line);
-			if ((strlen($trimmed) > 0) && !preg_match("/^[0-9a-fA-F]{40}/",$trimmed) && !preg_match("/^parent [0-9a-fA-F]{40}/",$trimmed)) {
-				if (!isset($commit['title'])) {
-					$commit['title'] = $trimmed;
-					if (strlen($trimmed) > GITPHP_TRIM_LENGTH)
-						$commit['title_short'] = substr($trimmed,0,GITPHP_TRIM_LENGTH) . "...";
-					else
-						$commit['title_short'] = $trimmed;
-				}
-				$comment[] = $trimmed;
-			}
-		}
-	}
-	$commit['comment'] = $comment;
-	$age = time() - $commit['committer_epoch'];
-	$commit['age'] = $age;
-	$commit['age_string'] = age_string($age);
-	date_default_timezone_set("UTC");
-	if ($age > 60*60*24*7*2) {
-		$commit['age_string_date'] = date("Y-m-d",$commit['committer_epoch']);
-		$commit['age_string_age'] = $commit['age_string'];
-	} else {
-		$commit['age_string_date'] = $commit['age_string'];
-		$commit['age_string_age'] = date("Y-m-d",$commit['committer_epoch']);
-	}
-	return $commit;
-}
-
-?>
-

--- a/include/gitutil.git_read_head.php
+++ /dev/null
@@ -1,29 +1,1 @@
-<?php
-/*
- *  gitutil.git_read_head.php
- *  gitphp: A PHP git repository browser
- *  Component: Git utility - read HEAD
- *
- *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
- */
 
-require_once('defs.commands.php');
-require_once(GITPHP_INCLUDEDIR . 'git/GitExe.class.php');
-
-function git_read_head()
-{
-	global $gitphp_current_project;
-
-	if (!$gitphp_current_project)
-		return '';
-
-	$exe = new GitPHP_GitExe(GitPHP_Config::GetInstance()->GetValue('gitbin'), $gitphp_current_project);
-
-	$args = array();
-	$args[] = '--verify';
-	$args[] = 'HEAD';
-	return trim($exe->Execute(GIT_REV_PARSE, $args));
-}
-
-?>
-

--- a/include/gitutil.git_read_projects.php
+++ b/include/gitutil.git_read_projects.php
@@ -30,7 +30,7 @@
 			if (is_file($projectroot . $ppath . "/HEAD"))
 			{
 				if ($projdata)
-					$ppath = git_project_info($projectroot, $ppath);
+					$ppath = git_project_info($ppath);
 				$projects[] = $ppath;
 			}
 		}
@@ -43,7 +43,7 @@
 				foreach ($plist as $pname => $ppath) {
 					if (is_file($projectroot . $ppath . "/HEAD")) {
 						if ($projdata)
-							$projs[] = git_project_info($projectroot, $ppath);
+							$projs[] = git_project_info($ppath);
 						else
 							$projs[] = $ppath;
 					}
@@ -61,7 +61,7 @@
 		for ($i = 0; $i < $len; ++$i) {
 			$p = substr($projects[$i],$cut + 1);
 			if ($projdata)
-				$projects[$i] = git_project_info($projectroot, $p);
+				$projects[$i] = git_project_info($p);
 			else
 				$projects[$i] = $p;
 		}

--- a/include/gitutil.git_read_ref.php
+++ b/include/gitutil.git_read_ref.php
@@ -10,7 +10,6 @@
  require_once('util.age_string.php');
  require_once('gitutil.git_get_type.php');
  require_once('gitutil.git_read_tag.php');
- require_once('gitutil.git_read_commit.php');
 
  function git_read_ref($ref_id, $ref_file)
  {
@@ -37,10 +36,10 @@
 		$tag = git_read_tag($ref_id);
 		$ref_item['comment'] = $tag['comment'];
 		if ($tag['type'] == "commit") {
-			$co = git_read_commit($tag['object']);
-			$ref_item['epoch'] = $co['committer_epoch'];
-			$ref_item['age_string'] = $co['age_string'];
-			$ref_item['age'] = $co['age'];
+			$co = $gitphp_current_project->GetCommit($tag['object']);
+			$ref_item['epoch'] = $co->GetCommitterEpoch();
+			$ref_item['age_string'] = age_string($co->GetAge());
+			$ref_item['age'] = $co->GetAge();
 		} else if (isset($tag['epoch'])) {
 			$age = time() - $tag['epoch'];
 			$ref_item['epoch'] = $tag['epoch'];
@@ -51,14 +50,14 @@
 		$ref_item['name'] = $tag['name'];
 		$ref_item['refid'] = $tag['object'];
 	} else if ($type == "commit") {
-		$co = git_read_commit($ref_id);
+		$co = $gitphp_current_project->GetCommit($ref_id);
 		$ref_item['reftype'] = "commit";
 		$ref_item['name'] = $ref_file;
-		$ref_item['title'] = $co['title'];
+		$ref_item['title'] = $co->GetTitle();
 		$ref_item['refid'] = $ref_id;
-		$ref_item['epoch'] = $co['committer_epoch'];
-		$ref_item['age_string'] = $co['age_string'];
-		$ref_item['age'] = $co['age'];
+		$ref_item['epoch'] = $co->GetCommitterEpoch();
+		$ref_item['age_string'] = age_string($co->GetAge());
+		$ref_item['age'] = $co->GetAge();
 	}
 
 	return $ref_item;

--- a/include/util.date_str.php
+++ b/include/util.date_str.php
@@ -9,6 +9,7 @@
 
 function date_str($epoch,$tz = "-0000")
 {
+	date_default_timezone_set('UTC');
 	$date = array();
 	$date['hour'] = date("H",$epoch);
 	$date['minute'] = date("i",$epoch);

file:a/index.php -> file:b/index.php
--- a/index.php
+++ b/index.php
@@ -156,43 +156,43 @@
 					break;
 				case "tree":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_tree.php');
-					git_tree(GitPHP_Config::GetInstance()->GetValue('projectroot'), $project, (isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['f']) ? $_GET['f'] : NULL), (isset($_GET['hb']) ? $_GET['hb'] : NULL));
+					git_tree((isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['f']) ? $_GET['f'] : NULL), (isset($_GET['hb']) ? $_GET['hb'] : NULL));
 					break;
 				case "shortlog":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_shortlog.php');
-					git_shortlog(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project,(isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['pg']) ? $_GET['pg'] : NULL));
+					git_shortlog((isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['pg']) ? $_GET['pg'] : NULL));
 					break;
 				case "log":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_log.php');
-					git_log(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project, (isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['pg']) ? $_GET['pg'] : NULL));
+					git_log((isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['pg']) ? $_GET['pg'] : NULL));
 					break;
 				case "commit":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_commit.php');
-					git_commit(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project,$_GET['h']);
+					git_commit($_GET['h']);
 					break;
 				case "commitdiff":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_commitdiff.php');
-					git_commitdiff(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project,$_GET['h'], (isset($_GET['hp']) ? $_GET['hp'] : NULL));
+					git_commitdiff($_GET['h'], (isset($_GET['hp']) ? $_GET['hp'] : NULL));
 					break;
 				case "commitdiff_plain":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_commitdiff_plain.php');
-					git_commitdiff_plain(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project,$_GET['h'],(isset($_GET['hp']) ? $_GET['hp'] : NULL));
+					git_commitdiff_plain($_GET['h'],(isset($_GET['hp']) ? $_GET['hp'] : NULL));
 					break;
 				case "heads":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_heads.php');
-					git_heads(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project);
+					git_heads();
 					break;
 				case "tags":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_tags.php');
-					git_tags(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project);
+					git_tags();
 					break;
 				case "rss":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_rss.php');
-					git_rss(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project);
+					git_rss();
 					break;
 				case "blob":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_blob.php');
-					git_blob(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project, (isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['f']) ? $_GET['f'] : NULL), (isset($_GET['hb']) ? $_GET['hb'] : NULL));
+					git_blob((isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['f']) ? $_GET['f'] : NULL), (isset($_GET['hb']) ? $_GET['hb'] : NULL));
 					break;
 				case "blob_plain":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_blob_plain.php');
@@ -200,7 +200,7 @@
 					break;
 				case "blobdiff":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_blobdiff.php');
-					git_blobdiff(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project,$_GET['h'],$_GET['hb'],$_GET['hp'],(isset($_GET['f']) ? $_GET['f'] : NULL));
+					git_blobdiff($_GET['h'],$_GET['hb'],$_GET['hp'],(isset($_GET['f']) ? $_GET['f'] : NULL));
 					break;
 				case "blobdiff_plain":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_blobdiff_plain.php');
@@ -208,7 +208,7 @@
 					break;
 				case "blame":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_blame.php');
-					git_blame(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project, (isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['f']) ? $_GET['f'] : NULL), (isset($_GET['hb']) ? $_GET['hb'] : NULL));
+					git_blame((isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['f']) ? $_GET['f'] : NULL), (isset($_GET['hb']) ? $_GET['hb'] : NULL));
 					break;
 				case "snapshot":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_snapshot.php');
@@ -216,20 +216,20 @@
 					break;
 				case "history":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_history.php');
-					git_history(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project, (isset($_GET['h']) ? $_GET['h'] : NULL),$_GET['f']);
+					git_history((isset($_GET['h']) ? $_GET['h'] : NULL),$_GET['f']);
 					break;
 				case "search":
 					if (isset($_GET['st']) && ($_GET['st'] == 'file')) {
 						require_once(GITPHP_INCLUDEDIR . 'display.git_search_files.php');
-						git_search_files(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project,(isset($_GET['h']) ? $_GET['h'] : NULL),(isset($_GET['s']) ? $_GET['s'] : NULL),(isset($_GET['pg']) ? $_GET['pg'] : 0));
+						git_search_files((isset($_GET['h']) ? $_GET['h'] : NULL),(isset($_GET['s']) ? $_GET['s'] : NULL),(isset($_GET['pg']) ? $_GET['pg'] : 0));
 					} else {
 						require_once(GITPHP_INCLUDEDIR . 'display.git_search.php');
-						git_search(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project,(isset($_GET['h']) ? $_GET['h'] : NULL),(isset($_GET['s']) ? $_GET['s'] : NULL),(isset($_GET['st']) ? $_GET['st'] : "commit"),(isset($_GET['pg']) ? $_GET['pg'] : 0));
+						git_search((isset($_GET['h']) ? $_GET['h'] : NULL),(isset($_GET['s']) ? $_GET['s'] : NULL),(isset($_GET['st']) ? $_GET['st'] : "commit"),(isset($_GET['pg']) ? $_GET['pg'] : 0));
 					}
 					break;
 				case "tag":
 					require_once(GITPHP_INCLUDEDIR . 'display.git_tag.php');
-					git_tag(GitPHP_Config::GetInstance()->GetValue('projectroot'),$project,$_GET['h']);
+					git_tag($_GET['h']);
 					break;
 				default:
 					$tpl->assign("validaction", FALSE);

--- a/templates/commit.tpl
+++ b/templates/commit.tpl
@@ -56,8 +56,8 @@
      {foreach from=$parents item=par}
        <tr>
          <td>parent</td>
-	 <td class="monospace"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$par}" class="list">{$par}</a></td>
-         <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$par}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}&hp={$par}">commitdiff</a></td>
+	 <td class="monospace"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$par->GetHash()}" class="list">{$par->GetHash()}</a></td>
+         <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$par->GetHash()}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}&hp={$par->GetHash()}">commitdiff</a></td>
        </tr>
      {/foreach}
    </table>

comments