Initial cache expiration
Initial cache expiration

--- a/config/gitphp.conf.php.example
+++ b/config/gitphp.conf.php.example
@@ -186,6 +186,13 @@
 $gitphp_conf['cache'] = FALSE;
 
 /*
+ * cacheexpire
+ * Attempts to automatically expire cache when a new commit renders
+ * it out of date.
+ */
+$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.

--- /dev/null
+++ b/include/cache.cache_expire.php
@@ -1,1 +1,36 @@
+<?php
+/*
+ *  cache.cache_expire.pehe
+ *  gitphp: A PHP git repository browser
+ *  Component: Cache - cache expire
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ */
 
+require_once('gitutil.git_read_refs.php');
+
+function cache_expire($projectroot, $project, $projectlist, $expireall = false)
+{
+	global $tpl;
+
+	if ($expireall) {
+		$tpl->clear_all_cache();
+		return;
+	}
+
+	if ((!isset($projectroot)) || (!isset($project)))
+		return;
+
+	$headlist = git_read_refs($projectroot, $project, "refs/heads");
+
+	if (count($headlist) > 0) {
+		$age = $headlist[0]['age'];
+
+		$tpl->clear_cache(null, sha1($project), null, $age);
+
+		$tpl->clear_cache('projectlist.tpl', sha1(serialize($projectlist)), null, $age);
+	}
+}
+
+?>
+

--- a/include/display.git_blob_plain.php
+++ b/include/display.git_blob_plain.php
@@ -12,26 +12,49 @@
 
 function git_blob_plain($projectroot,$project,$hash,$file)
 {
-	global $gitphp_conf;
+	global $gitphp_conf, $tpl;
 
-	if ($file)
-		$saveas = $file;
-	else
-		$saveas = $hash . ".txt";
+	$cachekey = sha1($project) . "|" . $hash . "|" . sha1($file);
 
-	$buffer = git_cat_file($projectroot . $project, $hash);
+	$buffer = null;
 
-	if ($gitphp_conf['filemimetype'])
-		$mime = file_mime($buffer, $file);
+	// XXX: Nasty hack to cache headers
+	if (!$tpl->is_cached('blobheaders.tpl', $cachekey)) {
+		if ($file)
+			$saveas = $file;
+		else
+			$saveas = $hash . ".txt";
 
-	if ($mime)
-		header("Content-type: " . $mime);
-	else
-		header("Content-type: text/plain; charset=UTF-8");
+		$buffer = git_cat_file($projectroot . $project, $hash);
 
-	header("Content-disposition: inline; filename=\"" . $saveas . "\"");
+		if ($gitphp_conf['filemimetype'])
+			$mime = file_mime($buffer, $file);
 
-	echo $buffer;
+		$headers = array();
+
+		if ($mime)
+			$headers[] = "Content-type: " . $mime;
+		else
+			$headers[] = "Content-type: text/plain; charset=UTF-8";
+
+		$headers[] = "Content-disposition: inline; filename=\"" . $saveas . "\"";
+
+		$tpl->assign("blobheaders", serialize($headers));
+	}
+	$out = $tpl->fetch('blobheaders.tpl', $cachekey);
+
+	$returnedheaders = unserialize($out);
+
+	foreach ($returnedheaders as $i => $header)
+		header($header);
+
+
+	if (!$tpl->is_cached('blobplain.tpl', $cachekey)) {
+		if (!$buffer)
+			$buffer = git_cat_file($projectroot . $project, $hash);
+		$tpl->assign("blob", $buffer);
+	}
+	$tpl->display('blobplain.tpl', $cachekey);
 }
 
 ?>

--- a/include/gitutil.git_read_refs.php
+++ b/include/gitutil.git_read_refs.php
@@ -46,7 +46,7 @@
 			$ref_item['type'] = $type;
 			$ref_item['id'] = $ref_id;
 			$ref_item['epoch'] = 0;
-			$ref_item['age'] = "unknown";
+			$ref_item['age_string'] = "unknown";
 
 			if ($type == "tag") {
 				$tag = git_read_tag($projectroot . $project, $ref_id);
@@ -54,11 +54,13 @@
 				if ($tag['type'] == "commit") {
 					$co = git_read_commit($projectroot . $project, $tag['object']);
 					$ref_item['epoch'] = $co['committer_epoch'];
-					$ref_item['age'] = $co['age_string'];
+					$ref_item['age_string'] = $co['age_string'];
+					$ref_item['age'] = $co['age'];
 				} else if (isset($tag['epoch'])) {
 					$age = time() - $tag['epoch'];
 					$ref_item['epoch'] = $tag['epoch'];
-					$ref_item['age'] = age_string($age);
+					$ref_item['age_string'] = age_string($age);
+					$ref_item['age'] = $age;
 				}
 				$ref_item['reftype'] = $tag['type'];
 				$ref_item['name'] = $tag['name'];
@@ -70,7 +72,8 @@
 				$ref_item['title'] = $co['title'];
 				$ref_item['refid'] = $ref_id;
 				$ref_item['epoch'] = $co['committer_epoch'];
-				$ref_item['age'] = $co['age_string'];
+				$ref_item['age_string'] = $co['age_string'];
+				$ref_item['age'] = $co['age'];
 			}
 			$reflist[] = $ref_item;
 		}

file:a/index.php -> file:b/index.php
--- a/index.php
+++ b/index.php
@@ -34,8 +34,8 @@
      	($_GET['a'] != "blob_plain") &&
      	($_GET['a'] != "blobdiff_plain") &&
      	($_GET['a'] != "rss") &&
-     	($_GET['a'] != "opml")
-     	($_GET['a'] != "snapshot"))) {
+     	($_GET['a'] != "opml") &&
+	($_GET['a'] != "snapshot"))) {
 	$tpl->load_filter('output','trimwhitespace');
 	$extraoutput = TRUE;
 }
@@ -56,6 +56,10 @@
  if ($gitphp_conf['cache']) {
  	$tpl->caching = 2;
 	$tpl->cache_lifetime = $gitphp_conf['cachelifetime'];
+	if ($gitphp_conf['cacheexpire']) {
+		require_once('include/cache.cache_expire.php');
+		cache_expire($gitphp_conf['projectroot'], (isset($_GET['p']) ? $_GET['p'] : null), $git_projects);
+	}
  }
 
 /*
@@ -90,7 +94,12 @@
 	$tpl->assign("filesearch",TRUE);
 
 
- if (isset($_GET['a']) && $_GET['a'] == "opml") {
+ if (isset($_GET['a']) && $_GET['a'] == "expire") {
+ 	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);
+ } else if (isset($_GET['a']) && $_GET['a'] == "opml") {
 	require_once('include/display.git_opml.php');
 	git_opml($gitphp_conf['projectroot'],$git_projects);
  } else if (isset($_GET['a']) && $_GET['a'] == "project_index") {

--- /dev/null
+++ b/templates/blobheaders.tpl
@@ -1,1 +1,9 @@
+{*
+ *  blobheaders.tpl
+ *  gitphp: A PHP git repository browser
+ *  Component: Blob header dummy template
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ *}
+{$blobheaders}
 

--- /dev/null
+++ b/templates/blobplain.tpl
@@ -1,1 +1,9 @@
+{*
+ *  blobplain.tpl
+ *  gitphp: A PHP git repository browser
+ *  Component: Blob plain template
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ *}
+{$blob}
 

--- a/templates/heads.tpl
+++ b/templates/heads.tpl
@@ -20,7 +20,7 @@
    {* Loop and display each head *}
    {foreach from=$headlist item=head}
      <tr class="{cycle values="light,dark"}">
-       <td><i>{$head.age}</i></td>
+       <td><i>{$head.age_string}</i></td>
        <td><a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/heads/{$head.name}" class="list"><b>{$head.name}</b></a></td>
        <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/heads/{$head.name}">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h=refs/heads/{$head.name}">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h=refs/heads/{$head.name}&hb={$head.name}">tree</a></td>
      </tr>

--- a/templates/project.tpl
+++ b/templates/project.tpl
@@ -57,7 +57,7 @@
          {if $smarty.section.tag.index == 16}
            <td><a href="{$SCRIPT_NAME}?p={$project}&a=tags">...</a></td>
          {else}
-           <td><i>{$taglist[tag].age}</i></td>
+           <td><i>{$taglist[tag].age_string}</i></td>
            <td><a href="{$SCRIPT_NAME}?p={$project}&a={$taglist[tag].reftype}&h={$taglist[tag].refid}" class="list"><b>{$taglist[tag].name}</b></a></td>
            <td>
              {if $taglist[tag].comment}
@@ -86,7 +86,7 @@
          {if $smarty.section.head.index == 16}
            <td><a href="{$SCRIPT_NAME}?p={$project}&a=heads">...</a></td>
          {else}
-           <td><i>{$headlist[head].age}</i></td>
+           <td><i>{$headlist[head].age_string}</i></td>
            <td><a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/heads/{$headlist[head].name}" class="list"><b>{$headlist[head].name}</b></td>
            <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/heads/{$headlist[head].name}">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h=refs/heads/{$headlist[head].name}">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h=refs/heads/{$headlist[head].name}&hb={$headlist[head].name}">tree</a></td>
          {/if}

--- a/templates/tags.tpl
+++ b/templates/tags.tpl
@@ -20,7 +20,7 @@
  <table cellspacing="0">
    {section name=tag loop=$taglist}
      <tr class="{cycle values="light,dark"}">
-       <td><i>{$taglist[tag].age}</i></td>
+       <td><i>{$taglist[tag].age_string}</i></td>
        <td><a href="{$SCRIPT_NAME}?p={$project}&a={$taglist[tag].reftype}&h={$taglist[tag].refid}" class="list"><b>{$taglist[tag].name}</b></a></td>
        <td>
          {if count($taglist[tag].comment) > 0}

comments