# portage_contents.py -- (Persistent) Contents File Management
# Copyright 1998-2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id: /var/cvsroot/gentoo-src/portage/pym/portage_contents.py,v 1.3.2.1 2005/01/16 02:35:33 carpaski Exp $


import os,string,types,sys,copy
import portage_exception
import portage_const

#import gettext
#gettext_t = gettext.translation('portage.contents', portage_const.LOCALE_DATA_PATH)
#_ = gettext_t.ugettext
def _(mystr):
	return mystr


FILES_KEY = "\0FILES\0"
OWNER_KEY = "\0OWNER\0"


def ContentsHandler(filename):
	infile = open(filename)
	myfiles = []
	mydirs  = []
	
	mylines = infile.readlines()
	infile.close()
	for line in mylines:
		if line[-1] == '\n':
			line   = line[:-1]
		parts  = string.split(line)

		mytype   = parts[0]
		mytarget = None

		if   mytype in ["dir","dev","fif"]:
			mypath = string.join(parts[1:])
		elif mytype == "obj":
			mypath = string.join(parts[1:-2])
		elif mytype == "sym":
			sl = string.join(parts[1:-1])
			sl = string.split(sl, " -> ")

			mypath   = sl[0]
			mytarget = sl[1]
		else:
			print _("Unknown type:"),mytype
		
		if mytype in ["dir"]:
			mydirs.append(mypath)
		else:
			myfiles.append(mypath)
	
	mydirs.sort()
	myfiles.sort()
	return myfiles,mydirs

class PathLookupTable:
	"""Creates a temporary lookup table for paths from files."""
	def __init__(self,dbname):
		#if not self.validLocation(dbname):
		#	raise portage_exception.InvalidLocation, dbname
		#self.base = copy.deepcopy(dbname)
		
		self.files = []
		self.pathtree = {}
	
	def addFromFile(self, filename, handler):
		if type(handler) != types.FunctionType:
			raise portage_exception.IncorrectParameter, _("Handler of type '%(type)s' not 'function'") % {"type": type(handler)}
	
		filelist,dirlist = handler(filename)
		filestat = os.stat(filename)

		if type(filelist) != types.ListType:
			raise portage_exception.InvalidDataType, _("%(handler)s returned an invalid file list") % {"handler": handler.__name__}
		if type(dirlist) != types.ListType:
			raise portage_exception.InvalidDataType, _("%(handler)s returned an invalid directory list") % {"handler": handler.__name__}

		for x in filelist:
			if not x:
				continue
			x = os.path.normpath(x)
			if len(x) > 1:
				if x[:2] == "//":
					x = x[1:]
			if type(x) != types.StringType:
				raise portage_exception.InvalidDataType, _("%(handler)s returned an invalid subelement in dataset") % {"handler": handler.__name__}
			xs = string.split(x, "/")
			self.addFilePath(xs,filename)
			
		for x in dirlist:
			if not x:
				continue
			x = os.path.normpath(x)
			if len(x) > 1:
				if x[:2] == "//":
					x = x[1:]
			if type(x) != types.StringType:
				raise portage_exception.InvalidDataType, _("%(handler)s returned an invalid subelement in dataset") % {"handler": handler.__name__}
			xs = string.split(x, "/")
			self.addDirectoryPath(xs,filename)
			
	def addDirectoryPath(self,split_path, owner):
		pt = self.pathtree
		for x in split_path:
			if x not in pt.keys():
				pt[x] = {FILES_KEY:{},OWNER_KEY:[]}
			if owner not in pt[x][OWNER_KEY]:
				pt[x][OWNER_KEY].append(owner[:])
			pt = pt[x]
		return pt

	def addFilePath(self,split_path, owner):
		pt = self.addDirectoryPath(split_path[:-1], owner)
		if split_path[-1] not in pt[FILES_KEY]:
			pt[FILES_KEY][split_path[-1][:]] = []
		if owner not in pt[FILES_KEY][split_path[-1][:]]:
			pt[FILES_KEY][split_path[-1][:]].append(owner[:])
		
	def whoProvides(self,path):
		if type(path) != types.StringType:
			raise portage_exception.InvalidData, _("Path passed is not a string: %(path)s") % {"path": path}
		x = os.path.normpath(path)
		if x[0:2] == '//':
			x = x[1:]
		
		xs = x.split("/")
		pt = self.pathtree
		final_dir = xs.pop(-1)
		for subpath in xs:
			if subpath in pt.keys():
				pt = pt[subpath]

		owners = []
		if final_dir in pt[FILES_KEY]:
			for x in pt[FILES_KEY][final_dir]:
				if x not in owners:
					owners.append(x[:])
		if final_dir in pt:
			for x in pt[final_dir][OWNER_KEY]:
				if x not in owners:
					owners.append(x[:])

		return owners



def test():
	import os
	plt = PathLookupTable("spork")
	for x in os.listdir("/var/db/pkg"):
		for y in os.listdir("/var/db/pkg/"+x):
			c_path = "/var/db/pkg/"+x+"/"+y+"/CONTENTS"
			if os.path.exists(c_path):
				plt.addFromFile(c_path, ContentsHandler)
	print "/bin/bash:",    plt.whoProvides("/bin/bash")
	print "/var/spool:",   plt.whoProvides("/var/spool")
	print "/etc/init.d",   plt.whoProvides("/etc/init.d")
	return plt
