Description links should not have an indent class
Description links should not have an indent class

file:a/README -> file:b/README
--- a/README
+++ b/README
@@ -79,3 +79,47 @@
 If you want to edit the text header that appears above the project list on the
 home page, edit templates/hometext.tpl.
 
+
+[Caching]
+
+To turn on caching, set the 'cache' config item to true.  Gitphp will cache
+every page's output, including plaintext output and binary output such as
+blobs and snapshots, for the number of seconds specified in the
+'cachelifetime' config key.
+The 'cacheexpire' key is recommended for most users.  With this option on,
+gitphp will attempt to keep the cache in sync by automatically expiring any
+cached pages that are older than the most recent commit, on any branch.
+It is a slight performance hit to make this check, but the performance hit
+is tiny compared to the gain you get from turning on caching.  It will
+avoid situations where users are getting a cached version of a page that
+isn't up to date and doesn't reflect the most recent commit, or worse,
+pages that have been cached at different times and show data from both
+before and after a commit (eg page 1 of the shortlog shows the most recent
+commit but page 1 of the log was cached a while ago and doesn't show the
+most recent commit).
+However, if your project is so active that commits are constantly coming in
+and invalidating the cache, rendering it useless, it would be better to
+turn cache expiration off and just set a really short cache lifetime of
+a few seconds.  In other words:
+
+Most users:
+* Set 'cacheexpire' to TRUE
+* Set 'cachelifetime' high, 3600 seconds (1 hour) or more.  -1 means
+  cache forever
+
+Extremely active projects, with commits every few seconds, or advanced
+users that know exactly how often commits come in and want to save
+the performance of the expiration check:
+* Set 'cacheexpire' to FALSE
+* Set 'cachelifetime' low, between 5-10 seconds.
+
+If you ever run into problems with your cache not syncing correctly, or
+showing out of date information, you can use the 'expire' action to force
+expiration of all cache.  This action is not linked anywhere because it
+is not supposed to be run by users, it's more of an administrative function.
+To use it, you want to set a=expire.  So, for example, you would visit this
+address in a browser (obviously with the correct path to your gitphp
+index.php):
+
+http://yourserver.com/gitphp/index.php?a=expire
+

--- a/config/gitphp.conf.php.example
+++ b/config/gitphp.conf.php.example
@@ -178,10 +178,7 @@
 /*
  * cache
  * Turns on smarty caching
- * Be very careful with this!  Due to varying cache lifetimes,
- * you could end up seeing a mix of pages from before and after
- * a commit!
- * If in doubt, leave this off
+ * Be careful with this.  If in doubt, leave it off
  */
 $gitphp_conf['cache'] = FALSE;
 
@@ -189,20 +186,25 @@
  * cacheexpire
  * Attempts to automatically expire cache when a new commit renders
  * it out of date.
+ * This is a good option for most users because it ensures the cache
+ * is always up to date and users are seeing correct information,
+ * although it is a slight performance hit.
+ * However, if your commits are coming in so quickly that the cache
+ * is constantly being expired, turn this off.
  */
 $gitphp_conf['cacheexpire'] = TRUE;
 
 /*
  * cachelifetime
  * Sets how long a page will be cached, in seconds
- * This will vary greatly depending on how active your projects are.
- * If you set it too high, commits that happen close to one another
- * will appear to be mixed together as the user navigates between
- * pages, depending on when each page was previously accessed and
- * its current cache lifetime.
- * If in doubt, set it to something extremely low, like 3 seconds.
- */
-$gitphp_conf['cachelifetime'] = 3;
+ * If you are automatically expiring the cache
+ * (see the 'cacheexpire' option above), then this can be set
+ * relatively high - 3600 seconds (1 hour) or even longer.
+ * -1 means no timeout.
+ * If you have turned cacheexpire off because of too many
+ * cache expirations, set this low (5-10 seconds).
+ */
+$gitphp_conf['cachelifetime'] = 3600;
 
 /*
  * git_projects

--- a/include/display.git_commit.php
+++ b/include/display.git_commit.php
@@ -56,7 +56,7 @@
 		$tpl->assign("difftreesize",count($difftree)+1);
 		$difftreelines = array();
 		foreach ($difftree as $i => $line) {
-			if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$",$line,$regs)) {
+			if (preg_match("/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/",$line,$regs)) {
 				$difftreeline = array();
 				$difftreeline["from_mode"] = $regs[1];
 				$difftreeline["to_mode"] = $regs[2];

--- a/include/display.git_commitdiff.php
+++ b/include/display.git_commitdiff.php
@@ -41,7 +41,7 @@
 		$tpl->assign("comment",$co['comment']);
 		$difftreelines = array();
 		foreach ($difftree as $i => $line) {
-			if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$",$line,$regs)) {
+			if (preg_match("/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/",$line,$regs)) {
 				$difftreeline = array();
 				$difftreeline["from_mode"] = $regs[1];
 				$difftreeline["to_mode"] = $regs[2];

--- a/include/display.git_commitdiff_plain.php
+++ b/include/display.git_commitdiff_plain.php
@@ -12,7 +12,7 @@
  require_once('util.script_url.php');
  require_once('gitutil.git_read_commit.php');
  require_once('gitutil.git_diff_tree.php');
- require_once('gitutil.git_rev_list.php');
+ require_once('gitutil.git_read_revlist.php');
  require_once('gitutil.read_info_ref.php');
  require_once('gitutil.git_diff.php');
 
@@ -37,14 +37,12 @@
 		$diffout = git_diff_tree($projectroot . $project, $hash_parent . " " . $hash);
 		$difftree = explode("\n",$diffout);
 		$refs = read_info_ref($projectroot . $project,"tags");
-		$listout = git_rev_list($projectroot . $project, "HEAD");
-		$tok = strtok($listout,"\n");
-		while ($tok !== false) {
-			if (isset($refs[$tok]))
-				$tagname = $refs[$tok];
-			if ($tok == $hash)
+		$listout = git_read_revlist($projectroot . $project, "HEAD");
+		foreach ($listout as $i => $rev) {
+			if (isset($refs[$rev]))
+				$tagname = $refs[$rev];
+			if ($rev == $hash)
 				break;
-			$tok = strtok("\n");
 		}
 		$ad = date_str($co['author_epoch'],$co['author_tz']);
 		$tpl->assign("from",$co['author']);
@@ -56,7 +54,7 @@
 		$tpl->assign("comment",$co['comment']);
 		$diffs = array();
 		foreach ($difftree as $i => $line) {
-			if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$",$line,$regs)) {
+			if (preg_match("/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/",$line,$regs)) {
 				if ($regs[5] == "A")
 					$diffs[] = git_diff($projectroot . $project, null, "/dev/null", $regs[4], "b/" . $regs[6]);
 				else if ($regs[5] == "D")

--- a/include/display.git_history.php
+++ b/include/display.git_history.php
@@ -36,9 +36,9 @@
 		$lines = explode("\n", $cmdout);
 		$historylines = array();
 		foreach ($lines as $i => $line) {
-			if (ereg("^([0-9a-fA-F]{40})",$line,$regs))
+			if (preg_match("/^([0-9a-fA-F]{40})/",$line,$regs))
 				$commit = $regs[1];
-			else if (ereg(":([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$",$line,$regs) && isset($commit)) {
+			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($projectroot . $project, $commit);
 					$historyline["agestringage"] = $co['age_string_age'];

--- a/include/display.git_rss.php
+++ b/include/display.git_rss.php
@@ -28,7 +28,7 @@
 		$tpl->assign("self",script_url());
 
 		$commitlines = array();
-		for ($i = 0; $i <= count($revlist); $i++) {
+		for ($i = 0; $i < count($revlist); $i++) {
 			$commit = $revlist[$i];
 			$co = git_read_commit($projectroot . $project, $commit);
 			if (($i >= 20) && ((time() - $co['committer_epoch']) > 48*60*60))
@@ -38,7 +38,7 @@
 			$diffout = git_diff_tree($projectroot . $project, $co['parent'] . " " . $co['id']);
 			$tok = strtok($diffout,"\n");
 			while ($tok !== false) {
-				if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$",$tok,$regs))
+				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))
 					$difftree[] = $regs[7];
 				$tok = strtok("\n");
 			}

--- a/include/display.git_search.php
+++ b/include/display.git_search.php
@@ -10,7 +10,7 @@
 require_once('defs.constants.php');
 require_once('util.highlight.php');
 require_once('gitutil.git_read_commit.php');
-require_once('gitutil.git_rev_list.php');
+require_once('gitutil.git_read_revlist.php');
 require_once('display.git_message.php');
 
 function git_search($projectroot, $project, $hash, $search, $searchtype, $page = 0)
@@ -37,7 +37,7 @@
 
 		$co = git_read_commit($projectroot . $project, $hash);
 
-		$revlist = explode("\n",trim(git_rev_list($projectroot . $project, $hash, 101, ($page * 100), FALSE, FALSE, $searchtype, $search)));
+		$revlist = git_read_revlist($projectroot . $project, $hash, 101, ($page * 100), FALSE, FALSE, $searchtype, $search);
 		if (count($revlist) < 1 || (strlen($revlist[0]) < 1)) {
 			git_message("No matches for '" . $search . "'.", FALSE, TRUE);
 			return;

--- a/include/display.git_tree.php
+++ b/include/display.git_tree.php
@@ -50,7 +50,7 @@
 		$treelines = array();
 		$tok = strtok($lsout,"\0");
 		while ($tok !== false) {
-			if (ereg("^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$",$tok,$regs)) {
+			if (preg_match("/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/",$tok,$regs)) {
 				$treeline = array();
 				$treeline["filemode"] = mode_str($regs[1]);
 				$treeline["type"] = $regs[2];

--- a/include/gitutil.git_exec_nix.php
+++ b/include/gitutil.git_exec_nix.php
@@ -10,7 +10,10 @@
  function git_exec_nix($project, $command)
  {
  	global $gitphp_conf;
-	$cmd = $gitphp_conf['gitbin'] . " --git-dir=" . $project . " " . $command;
+	$cmd = $gitphp_conf['gitbin'];
+	if (isset($project) && (strlen($project) > 0))
+		$cmd .= " --git-dir=" . $project;
+	$cmd .= " " . $command;
 	return shell_exec($cmd);
  }
 

--- a/include/gitutil.git_exec_win.php
+++ b/include/gitutil.git_exec_win.php
@@ -10,7 +10,10 @@
 function git_exec_win($project, $command)
 {
 	global $gitphp_conf;
-	$cmd = $gitphp_conf['gitbin'] . " --git-dir=" . $project . " " . $command;
+	$cmd = $gitphp_conf['gitbin'];
+	if (isset($project) && (strlen($project) > 0))
+		$cmd .= " --git-dir=" . $project;
+	$cmd .= " " . $command;
 	return shell_exec($cmd);
 }
 

--- a/include/gitutil.git_filesearch.php
+++ b/include/gitutil.git_filesearch.php
@@ -21,9 +21,9 @@
 	$lines = explode("\n",$grepout);
 	foreach ($lines as $j => $line) {
 		if ($case)
-			$ret = ereg("^([^:]+):([^:]+):(.*" . quotemeta($search) . ".*)",$line,$regs);
+			$ret = preg_match("/^([^:]+):([^:]+):(.*" . quotemeta($search) . ".*)/",$line,$regs);
 		else
-			$ret = eregi("^([^:]+):([^:]+):(.*" . quotemeta($search) . ".*)",$line,$regs);
+			$ret = preg_match(("/^([^:]+):([^:]+):(.*" . quotemeta($search) . ".*)/i",$line,$regs);
 		if ($ret) {
 			$fname = trim($regs[2]);
 			if (!isset($matches[$fname])) {
@@ -40,16 +40,16 @@
 	 $lsout = git_ls_tree($project, $hash, false, true);
 	 $entries = explode("\n",$lsout);
 	 foreach ($entries as $j => $line) {
-		$ret = ereg("^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)",$line,$regs);
+		$ret = preg_match("/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)/",$line,$regs);
 		$fname = trim($regs[4]);
 		if (isset($matches[$fname])) {
 			$matches[$fname]['hash'] = $regs[3];
 			$matches[$fname]['type'] = $regs[2];
 		} else {
 			if ($case)
-				$ret = ereg("^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.*" . quotemeta($search) . "[^/]*)$",$line,$regs);
+				$ret = preg_match("/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.*" . quotemeta($search) . "[^/]*)$/",$line,$regs);
 			else
-				$ret = eregi("^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.*" . quotemeta($search) . "[^/]*)$",$line,$regs);
+				$ret = preg_match("/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.*" . quotemeta($search) . "[^/]*)$/i",$line,$regs);
 			if ($ret) {
 				$fname = trim($regs[4]);
 				$matches[$fname] = array();

--- a/include/gitutil.git_get_hash_by_path.php
+++ b/include/gitutil.git_get_hash_by_path.php
@@ -18,7 +18,7 @@
 		$lsout = git_ls_tree($project, $tree);
 		$entries = explode("\n",$lsout);
 		foreach ($entries as $j => $line) {
-			if (ereg("^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$",$line,$regs)) {
+			if (preg_match("/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/",$line,$regs)) {
 				if ($regs[4] == $part) {
 					if ($i == ($partcount)-1)
 						return $regs[3];

--- a/include/gitutil.git_read_commit.php
+++ b/include/gitutil.git_read_commit.php
@@ -9,13 +9,12 @@
 
  require_once('defs.constants.php');
  require_once('util.age_string.php');
- require_once('gitutil.git_rev_list.php');
+ require_once('gitutil.git_read_revlist.php');
 
 function git_read_commit($proj,$head)
 {
-	$revlist = git_rev_list($proj,$head,1,NULL,TRUE,TRUE);
-	$lines = explode("\n",$revlist);
-	if (!($lines[0]) || !ereg("^[0-9a-fA-F]{40}",$lines[0]))
+	$lines = git_read_revlist($proj,$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]," ");
@@ -31,25 +30,25 @@
 		$commit['parent'] = $parents[0];
 	$comment = array();
 	foreach ($lines as $i => $line) {
-		if (ereg("^tree ([0-9a-fA-F]{40})$",$line,$regs))
+		if (preg_match("/^tree ([0-9a-fA-F]{40})$/",$line,$regs))
 			$commit['tree'] = $regs[1];
-		else if (ereg("^author (.*) ([0-9]+) (.*)$",$line,$regs)) {
+		else if (preg_match("/^author (.*) ([0-9]+) (.*)$/",$line,$regs)) {
 			$commit['author'] = $regs[1];
 			$commit['author_epoch'] = $regs[2];
 			$commit['author_tz'] = $regs[3];
-			if (ereg("^([^<]+) <",$commit['author'],$r))
+			if (preg_match("/^([^<]+) </",$commit['author'],$r))
 				$commit['author_name'] = $r[1];
 			else
 				$commit['author_name'] = $commit['author'];
-		} else if (ereg("^committer (.*) ([0-9]+) (.*)$",$line,$regs)) {
+		} 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'] = ereg_replace(" <.*","",$commit['committer_name']);
+			$commit['committer_name'] = preg_replace("/ <.*/","",$commit['committer_name']);
 		} else {
 			$trimmed = trim($line);
-			if ((strlen($trimmed) > 0) && !ereg("^[0-9a-fA-F]{40}",$trimmed) && !ereg("^parent [0-9a-fA-F]{40}",$trimmed)) {
+			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)

--- a/include/gitutil.git_read_revlist.php
+++ b/include/gitutil.git_read_revlist.php
@@ -8,11 +8,39 @@
  */
 
  require_once('gitutil.git_rev_list.php');
+ require_once('gitutil.git_version.php');
 
-function git_read_revlist($proj,$head,$count,$skip = NULL)
+function git_read_revlist($proj,$head,$count = NULL,$skip = NULL,$header = FALSE,$parents = FALSE,$greptype = NULL, $search = NULL)
 {
-	$revs = trim(git_rev_list($proj,$head,$count, $skip));
+	$passedskip = $skip;
+	$passedcount = $count;
+	$canskip = true;
+
+	if (isset($skip) && ($skip > 0)) {
+		$version = git_version();
+		if (isset($version) && (strlen($version) > 0)) {
+			$splitver = explode(".",$version);
+
+			/* Skip only appears in git >= 1.5.0 */
+			if (($splitver[0] < 1) || (($splitver[0] == 1) && ($splitver[1] < 5))) {
+				$canskip = false;
+				$passedskip = null;
+				$passedcount += $skip;
+			}
+		}
+	}
+
+	$revs = trim(git_rev_list($proj,$head, $passedcount, $passedskip, $header, $parents, $greptype, $search));
 	$revlist = explode("\n",$revs);
+
+	if ((!$canskip) && ($skip > 0)) {
+		$tmp = array();
+		$revcount = count($revlist);
+		for ($i = $skip; $i < $revcount; $i++)
+			$tmp[] = $revlist[$i];
+		return $tmp;
+	}
+
 	return $revlist;
 }
 

--- a/include/gitutil.git_read_tag.php
+++ b/include/gitutil.git_read_tag.php
@@ -17,13 +17,13 @@
 	$comment = array();
 	$tok = strtok($tagout,"\n");
 	while ($tok !== false) {
-		if (ereg("^object ([0-9a-fA-F]{40})$",$tok,$regs))
+		if (preg_match("/^object ([0-9a-fA-F]{40})$/",$tok,$regs))
 			$tag['object'] = $regs[1];
-		else if (ereg("^type (.+)$",$tok,$regs))
+		else if (preg_match("/^type (.+)$/",$tok,$regs))
 			$tag['type'] = $regs[1];
-		else if (ereg("^tag (.+)$",$tok,$regs))
+		else if (preg_match("/^tag (.+)$/",$tok,$regs))
 			$tag['name'] = $regs[1];
-		else if (ereg("^tagger (.*) ([0-9]+) (.*)$",$tok,$regs)) {
+		else if (preg_match("/^tagger (.*) ([0-9]+) (.*)$/",$tok,$regs)) {
 			$tag['author'] = $regs[1];
 			$tag['epoch'] = $regs[2];
 			$tag['tz'] = $regs[3];

--- /dev/null
+++ b/include/gitutil.git_version.php
@@ -1,1 +1,21 @@
+<?php
+/*
+ *  gitutil.git_version.php
+ *  gitphp: A PHP git repository browser
+ *  Component: Git utility - version
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ */
 
+ require_once('gitutil.git_exec.php');
+
+ function git_version()
+ {
+ 	$verstr = explode(" ",git_exec(null, "--version"));
+	if (($verstr[0] == "git") && ($verstr[1] == "version"))
+		return $verstr[2];
+	return null;
+ }
+
+?>
+

--- a/include/gitutil.read_info_ref.php
+++ b/include/gitutil.read_info_ref.php
@@ -17,7 +17,7 @@
 	$showrefs = git_exec($project, $cmd);
 	$lines = explode("\n",$showrefs);
 	foreach ($lines as $no => $line) {
-		if (ereg("^([0-9a-fA-F]{40}) .*" . $type . "/([^\^]+)",$line,$regs)) {
+		if (preg_match("`^([0-9a-fA-F]{40}) .*" . $type . "/([^\^]+)`",$line,$regs)) {
 			if (isset($refs[$regs[1]]))
 				$refs[$regs[1]] .= " / " . $regs[2];
 			else

--- a/include/util.date_str.php
+++ b/include/util.date_str.php
@@ -17,7 +17,7 @@
 	$date['month'] = date("M",$epoch);
 	$date['rfc2822'] = date("r",$epoch);
 	$date['mday-time'] = date("d M H:i",$epoch);
-	if (ereg("^([+\-][0-9][0-9])([0-9][0-9])$",$tz,$regs)) {
+	if (preg_match("/^([+\-][0-9][0-9])([0-9][0-9])$/",$tz,$regs)) {
 		$local = $epoch + ((((int)$regs[1]) + ($regs[2]/60)) * 3600);
 		$date['hour_local'] = date("H",$local);
 		$date['minute_local'] = date("i",$local);

--- a/include/util.highlight.php
+++ b/include/util.highlight.php
@@ -9,7 +9,7 @@
 
 function highlight($haystack, $needle, $highlightclass, $trimlen = NULL, $escape = false)
 {
-	if (eregi("(.*)(" . quotemeta($needle) . ")(.*)",$haystack,$regs)) {
+	if (preg_match("/(.*)(" . quotemeta($needle) . ")(.*)/i",$haystack,$regs)) {
 		if (isset($trimlen) && ($trimlen > 0)) {
 			$linelen = strlen($regs[0]);
 			if ($linelen > $trimlen) {

--- a/include/version.php
+++ b/include/version.php
@@ -7,7 +7,7 @@
  *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
  */
 
- $gitphp_version = "0.0.7";
+ $gitphp_version = "0.0.8";
  $gitphp_appstring = "gitphp $gitphp_version";
 
 ?>

file:a/index.php -> file:b/index.php
--- a/index.php
+++ b/index.php
@@ -28,7 +28,7 @@
   * Instantiate Smarty
   */
  require_once($gitphp_conf['smarty_prefix'] . "Smarty.class.php");
- $tpl =& new Smarty;
+ $tpl = new Smarty;
  if ((!isset($_GET['a'])) || (
      	($_GET['a'] != "commitdiff_plain") &&
      	($_GET['a'] != "blob_plain") &&
@@ -55,10 +55,11 @@
  */
  if ($gitphp_conf['cache']) {
  	$tpl->caching = 2;
-	$tpl->cache_lifetime = $gitphp_conf['cachelifetime'];
-	if ($gitphp_conf['cacheexpire']) {
+	if (isset($gitphp_conf['cachelifetime']))
+		$tpl->cache_lifetime = $gitphp_conf['cachelifetime'];
+	if (!(isset($gitphp_conf['cacheexpire']) && ($gitphp_conf['cacheexpire'] === FALSE))) {
 		require_once('include/cache.cache_expire.php');
-		cache_expire($gitphp_conf['projectroot'], (isset($_GET['p']) ? $_GET['p'] : null), $git_projects);
+		cache_expire($gitphp_conf['projectroot'], (isset($_GET['p']) ? $_GET['p'] : null), (isset($git_projects) ? $git_projects : null));
 	}
  }
 
@@ -98,7 +99,7 @@
  	require_once('include/cache.cache_expire.php');
 	require_once('include/display.git_message.php');
 	cache_expire(null, null, null, true);
-	git_message("Cache expired", true);
+	git_message("Cache expired");
  } else if (isset($_GET['a']) && $_GET['a'] == "opml") {
 	require_once('include/display.git_opml.php');
 	git_opml($gitphp_conf['projectroot'],$git_projects);
@@ -207,7 +208,7 @@
 	}
  } else {
 	require_once('include/display.git_project_list.php');
- 	git_project_list($gitphp_conf['projectroot'],$git_projects,(isset($_GET['o']) ? $_GET['o'] : "project"));
+	git_project_list($gitphp_conf['projectroot'], (isset($git_projects) ? $git_projects : null), (isset($_GET['o']) ? $_GET['o'] : "project"));
  }
 
  if ($gitphp_conf['debug'] && $extraoutput)

--- a/templates/projectlist.tpl
+++ b/templates/projectlist.tpl
@@ -58,7 +58,7 @@
             <td>
               <a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=summary" class="list {if $categ != "none"}indent{/if}">{$plist[proj].project}</a>
             </td>
-            <td>{$plist[proj].descr}</td>
+            <td><a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=summary" class="list">{$plist[proj].descr}</a></td>
             <td><i>{$plist[proj].owner}</i></td>
             <td>
               {if $plist[proj].age < 7200}   {* 60*60*2, or 2 hours *}
@@ -82,7 +82,7 @@
           <td>
             <a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=summary" class="list">{$projects[proj].project}</a>
           </td>
-          <td>{$projects[proj].descr}</td>
+          <td><a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=summary" class="list">{$projects[proj].descr}</a></td>
           <td><i>{$projects[proj].owner}</i></td>
           <td>
             {if $projects[proj].age < 7200}   {* 60*60*2, or 2 hours *}

comments