Bug #290428 - Update mtime of /var/db/pkg and category subdirectories when
stuff inside is modified, so that consumers can use directory mtimes to
validate caches.

svn path=/main/trunk/; revision=14735
diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index c103cbd..049db6e 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -52,6 +52,7 @@
 import logging
 import os as _os
 import sys
+import time
 import warnings
 
 try:
@@ -849,6 +850,19 @@
 			rValue = _os.path.join(rValue, filename)
 		return rValue
 
+	def _bump_mtime(self, cpv):
+		"""
+		This is called before an after any modifications, so that consumers
+		can use directory mtimes to validate caches. See bug #290428.
+		"""
+		base = self.root + _os.sep + VDB_PATH
+		cat = catsplit(cpv)[0]
+		catdir = base + _os.sep + cat
+		t = time.time()
+		t = (t, t)
+		for x in (catdir, base):
+			os.utime(x, t)
+
 	def cpv_exists(self, mykey):
 		"Tells us whether an actual ebuild exists on disk (no masking)"
 		return os.path.exists(self.getpath(mykey))
@@ -1301,6 +1315,7 @@
 		return results
 
 	def aux_update(self, cpv, values):
+		self._bump_mtime(cpv)
 		cat, pkg = catsplit(cpv)
 		mylink = dblink(cat, pkg, self.root, self.settings,
 		treetype="vartree", vartree=self.vartree)
@@ -1314,6 +1329,7 @@
 					os.unlink(os.path.join(self.getpath(cpv), k))
 				except EnvironmentError:
 					pass
+		self._bump_mtime(cpv)
 
 	def counter_tick(self, myroot, mycpv=None):
 		return self.counter_tick_core(myroot, incrementing=1, mycpv=mycpv)
@@ -1435,9 +1451,11 @@
 				removed += 1
 
 		if removed:
+			self._bump_mtime(pkg.mycpv)
 			f = atomic_ofstream(os.path.join(pkg.dbdir, "CONTENTS"))
 			write_contents(new_contents, root, f)
 			f.close()
+			self._bump_mtime(pkg.mycpv)
 			pkg._clear_contents_cache()
 
 	class _owners_cache(object):
@@ -2067,6 +2085,7 @@
 		The caller must ensure that lockdb() and unlockdb() are called
 		before and after this method.
 		"""
+		self.vartree.dbapi._bump_mtime(self.mycpv)
 		showMessage = self._display_merge
 		if self.vartree.dbapi._categories is not None:
 			self.vartree.dbapi._categories = None
@@ -2208,6 +2227,7 @@
 				self.vartree.dbapi.plib_registry.pruneNonExisting()
 
 		finally:
+			self.vartree.dbapi._bump_mtime(self.mycpv)
 			if builddir_lock:
 				try:
 					if myebuildpath:
@@ -4341,6 +4361,7 @@
 		mydbapi=None, prev_mtimes=None):
 		retval = -1
 		self.lockdb()
+		self.vartree.dbapi._bump_mtime(self.mycpv)
 		try:
 			self.vartree.dbapi.plib_registry.load()
 			self.vartree.dbapi.plib_registry.pruneNonExisting()
@@ -4366,6 +4387,7 @@
 		finally:
 			self.vartree.dbapi.linkmap._clear_cache()
 			self.unlockdb()
+			self.vartree.dbapi._bump_mtime(self.mycpv)
 		return retval
 
 	def getstring(self,name):