'''Class to read the RedHat RPM configuration file /etc/rpmrc and ~/.rpmrc

Dan Fandrich <dan@fch.wimsey.bc.ca>
$Id: rpmrc.py,v 1.2 1998/06/12 20:02:41 dan Exp $

$Log: rpmrc.py,v $
Revision 1.2  1998/06/12 20:02:41  dan
Added Id and Log keywords.

Feb. 4, 1997
Dec. 31, 1996
'''

from string import digits, split, lower, strip
from os import path, popen
from danutil import getenviron
from regex import compile

# Default RedHat root directory
def_redhat_dir = '/usr/src/redhat'

# RPM configuration file
def_rpm_rpmrc = '/usr/lib/rpmrc'

class RPMrc:
	'''Class to read the RPM configuration file

	Reads the files ~/.rpmrc and /etc/rpmrc to get RPM configuration
	information.

	Example: rpmrc = RPMrc(); root = rpmrc['topdir']
		 archflags = rpmrc['optflags'][rpmrc['arch']]
		 canon = rpmrc.gettags('os_canon')

	Any tag string can be used as an index into the class (e.g. 'topdir').
	The gettags() method can be used to get all matching lines, not just
	the first.
	Several special tags are also available:

	'rpm_dir'	same as 'topdir' value, or '/usr/src/redhat' if
			topdir doesn't exist
	'spec_dir'	absolute path to SPECS directory
	'binrpm_dir'	absolute path to SPECS directory (append 'arch' value
			to path to get the actual directory)
	'arch'		'', or system architecture if arch_sensitive
	'optflags'	dictionary containing compiler flags, indexed by
			'arch' value
	'''

	def gettag(self,tag):
		'Parse RPM config files to find first specific item'
		value = self.gettags(tag)
		if value:
			return value[0]
		return None	# couldn't find requested entry in file

	def gettags(self,tag):
		'Parse RPM config files to find all lines with a specific item'
		# compile regex to look for key, stripping whitespace
		tag_re = compile('^\([^:]*\)[ \t]*:[ \t]*\(.*\)$')
		matches = []
		for l in self.rpmrclines:
			l = strip(l)
			if not l:				# blank line
				continue
			if l[0] == '#':			# comment line
				continue
			if tag_re.search(l) >= 0:
				thistag = lower(tag_re.group(1))
				if thistag == tag:	# match!
					matches.append(strip(tag_re.group(2)))
		return matches

	def gettagsdict(self,tag):
		'''Parse RPM config files to find all lines with a specific
		item and return in dictionary form.
		The dictionary keys are taken to be whatever appears before
		a colon.
		'''
		values = self.gettags(tag)
		if not values:
			return None	# couldn't find requested entry in file

		# compile regex to look for key, stripping whitespace
		key_re = compile('^\([^:]*\)[ \t]*:[ \t]*\(.*\)')
		dict = {}
		for entry in values:
			if key_re.search(entry) >= 0:
				key = key_re.group(1)
				value = key_re.group(2)
			else:
				key = entry	# default to whole entry
				value = ''			
			# Don't replace earlier key in dictionary, since
			# earlier ones must override later ones
			if not dict.has_key(key):
				dict[key] = value

		return dict

	def readrpmrc(self, rcfile):
		'Return the contents of the rpmrc file(s)'

		# Read the ~/.rpmrc file first
		rpmrc = path.join(getenviron('HOME'), '.rpmrc')
		try:
			lines = open(rpmrc).readlines()
		except IOError:
			lines = []

		# Read the given rpmrc file
		try:
			lines = lines + open(rcfile).readlines()
		except IOError:
			pass

		# Read the /usr/lib/rpmrc file
		try:
			lines = lines + open(def_rpm_rpmrc).readlines()
		except IOError:
			pass

		return lines

	def __getitem__(self,key):
		'''Allow accessing items with the syntax rpmclass['topdir']

		Some items come from the dictionary which has been configured
		with default values. Other items come directly from the
		configuration file.
		'''
		try:
			return self.tags[key]
		except:
			return self.gettag(key)

	def __init__(self, rcfile='/etc/rpmrc'):
		'''Read the RPM configuration files

		Set certain fields to default values here. Others are
		read unfiltered.
		'''

		# Read the lines from all configuration files
		self.rpmrclines = self.readrpmrc(rcfile)
		self.tags = {}

		# Create the special tags and put them into a dictionary

		# RedHat RPM files root directory
		self.tags['rpm_dir'] = self.gettag('topdir')
		if not self.tags['rpm_dir']:
			self.tags['rpm_dir'] = def_redhat_dir

		# location to put .spec files
		self.tags['spec_dir'] = self.gettag('specdir')
		if not self.tags['spec_dir']:
			self.tags['spec_dir'] = 'SPECS'
		self.tags['spec_dir'] = \
			path.join(self.tags['rpm_dir'], self.tags['spec_dir'])

		# location to put .rpm binary packages
		self.tags['binrpm_dir'] = self.gettag('rpmdir')
		if not self.tags['binrpm_dir']:
			self.tags['binrpm_dir'] = 'RPMS'
		self.tags['binrpm_dir'] = \
			path.join(self.tags['rpm_dir'], self.tags['binrpm_dir'])

		# determine whether the architecture is relevant
		arch = self.gettag('arch_sensitive')
		if arch and atoi(arch) == 0:
			self.tags['arch'] = ''
		else:
			self.tags['arch'] = strip(popen('arch').readline())
			if self.tags['arch'][0] == 'i' \
			   and self.tags['arch'][1] in digits:
				self.tags['arch'] = 'i386'
			self.tags['binrpm_dir'] = \
				path.join(self.tags['binrpm_dir'], self.tags['arch'])

		# get all the optflags lines and put them into a dict
		# prime the dictionary with blank flags for our architecture
		optflagsdict = {self.tags['arch']:''}
		for optline in self.gettags('optflags'):
			arch = split(optline)[0]
			optflagsdict[arch] = optline[len(split(optline)[0])+1:]
		self.tags['optflags'] = optflagsdict
