# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

import errno, os, re, sys

from portage.util import ConfigProtect, grabfile, new_protect_filename, \
	normalize_path, write_atomic, writemsg
from portage.exception import DirectoryNotFound, PortageException
from portage.versions import ververify
from portage.dep import dep_getkey, get_operator, isvalidatom, isjustname, \
	remove_slot
from portage.const import USER_CONFIG_PATH, WORLD_FILE

ignored_dbentries = ("CONTENTS", "environment.bz2")

def update_dbentry(update_cmd, mycontent):
	if update_cmd[0] == "move":
		old_value, new_value = update_cmd[1], update_cmd[2]
		if old_value in mycontent:
			old_value = re.escape(old_value);
			mycontent = re.sub(old_value+"(:|$|\\s)", new_value+"\\1", mycontent)
			def myreplace(matchobj):
				# Strip slot and * operator if necessary
				# so that ververify works.
				ver = remove_slot(matchobj.group(2))
				ver = ver.rstrip("*")
				if ververify(ver):
					return "%s-%s" % (new_value, matchobj.group(2))
				else:
					return "".join(matchobj.groups())
			mycontent = re.sub("(%s-)(\\S*)" % old_value, myreplace, mycontent)
	elif update_cmd[0] == "slotmove" and get_operator(update_cmd[1]) is None:
		pkg, origslot, newslot = update_cmd[1:]
		old_value = "%s:%s" % (pkg, origslot)
		if old_value in mycontent:
			old_value = re.escape(old_value)
			new_value = "%s:%s" % (pkg, newslot)
			mycontent = re.sub(old_value+"($|\\s)", new_value+"\\1", mycontent)
	return mycontent

def update_dbentries(update_iter, mydata):
	"""Performs update commands and returns a
	dict containing only the updated items."""
	updated_items = {}
	for k, mycontent in mydata.iteritems():
		if k not in ignored_dbentries:
			orig_content = mycontent
			for update_cmd in update_iter:
				mycontent = update_dbentry(update_cmd, mycontent)
			if mycontent != orig_content:
				updated_items[k] = mycontent
	return updated_items

def fixdbentries(update_iter, dbdir):
	"""Performs update commands which result in search and replace operations
	for each of the files in dbdir (excluding CONTENTS and environment.bz2).
	Returns True when actual modifications are necessary and False otherwise."""
	mydata = {}
	for myfile in [f for f in os.listdir(dbdir) if f not in ignored_dbentries]:
		file_path = os.path.join(dbdir, myfile)
		f = open(file_path, "r")
		mydata[myfile] = f.read()
		f.close()
	updated_items = update_dbentries(update_iter, mydata)
	for myfile, mycontent in updated_items.iteritems():
		file_path = os.path.join(dbdir, myfile)
		write_atomic(file_path, mycontent)
	return len(updated_items) > 0

def grab_updates(updpath, prev_mtimes=None):
	"""Returns all the updates from the given directory as a sorted list of
	tuples, each containing (file_path, statobj, content).  If prev_mtimes is
	given then only updates with differing mtimes are considered."""
	try:
		mylist = os.listdir(updpath)
	except OSError, oe:
		if oe.errno == errno.ENOENT:
			raise DirectoryNotFound(updpath)
		raise
	if prev_mtimes is None:
		prev_mtimes = {}
	# validate the file name (filter out CVS directory, etc...)
	mylist = [myfile for myfile in mylist if len(myfile) == 7 and myfile[1:3] == "Q-"]
	if len(mylist) == 0:
		return []
	
	# update names are mangled to make them sort properly
	mylist = [myfile[3:]+"-"+myfile[:2] for myfile in mylist]
	mylist.sort()
	mylist = [myfile[5:]+"-"+myfile[:4] for myfile in mylist]

	update_data = []
	for myfile in mylist:
		file_path = os.path.join(updpath, myfile)
		mystat = os.stat(file_path)
		if file_path not in prev_mtimes or \
		long(prev_mtimes[file_path]) != long(mystat.st_mtime):
			f = open(file_path)
			content = f.read()
			f.close()
			update_data.append((file_path, mystat, content))
	return update_data

def parse_updates(mycontent):
	"""Valid updates are returned as a list of split update commands."""
	myupd = []
	errors = []
	mylines = mycontent.splitlines()
	for myline in mylines:
		mysplit = myline.split()
		if len(mysplit) == 0:
			continue
		if mysplit[0] not in ("move", "slotmove"):
			errors.append("ERROR: Update type not recognized '%s'" % myline)
			continue
		if mysplit[0] == "move":
			if len(mysplit) != 3:
				errors.append("ERROR: Update command invalid '%s'" % myline)
				continue
			orig_value, new_value = mysplit[1], mysplit[2]
			for cp in (orig_value, new_value):
				if not (isvalidatom(cp) and isjustname(cp)):
					errors.append(
						"ERROR: Malformed update entry '%s'" % myline)
					continue
		if mysplit[0] == "slotmove":
			if len(mysplit)!=4:
				errors.append("ERROR: Update command invalid '%s'" % myline)
				continue
			pkg, origslot, newslot = mysplit[1], mysplit[2], mysplit[3]
			if not isvalidatom(pkg):
				errors.append("ERROR: Malformed update entry '%s'" % myline)
				continue
		
		# The list of valid updates is filtered by continue statements above.
		myupd.append(mysplit)
	return myupd, errors

def update_config_files(config_root, protect, protect_mask, update_iter):
	"""Perform global updates on /etc/portage/package.* and the world file.
	config_root - location of files to update
	protect - list of paths from CONFIG_PROTECT
	protect_mask - list of paths from CONFIG_PROTECT_MASK
	update_iter - list of update commands as returned from parse_updates()"""
	config_root = normalize_path(config_root)
	update_files = {}
	file_contents = {}
	myxfiles = ["package.mask", "package.unmask", \
		"package.keywords", "package.use"]
	myxfiles += [os.path.join("profile", x) for x in myxfiles]
	abs_user_config = os.path.join(config_root,
		USER_CONFIG_PATH.lstrip(os.path.sep))
	recursivefiles = []
	for x in myxfiles:
		config_file = os.path.join(abs_user_config, x)
		if os.path.isdir(config_file):
			for parent, dirs, files in os.walk(config_file):
				for y in dirs:
					if y.startswith("."):
						dirs.remove(y)
				for y in files:
					if y.startswith("."):
						continue
					recursivefiles.append(
						os.path.join(parent, y)[len(abs_user_config) + 1:])
		else:
			recursivefiles.append(x)
	myxfiles = recursivefiles
	for x in myxfiles:
		try:
			myfile = open(os.path.join(abs_user_config, x),"r")
			file_contents[x] = myfile.readlines()
			myfile.close()
		except IOError:
			if file_contents.has_key(x):
				del file_contents[x]
			continue

	worldlist = grabfile(os.path.join(config_root, WORLD_FILE))
	modified = False
	for update_cmd in update_iter:
		for pos, atom in enumerate(worldlist):
			new_atom = update_dbentry(update_cmd, atom)
			if atom != new_atom:
				worldlist[pos] = new_atom
				modified = True
	if modified:
		worldlist.sort()
		write_atomic(os.path.join(config_root, WORLD_FILE),
			"\n".join(worldlist)+"\n")

	# update /etc/portage/packages.*
	ignore_line_re = re.compile(r'^#|^\s*$')
	for update_cmd in update_iter:
		for x, contents in file_contents.iteritems():
			for pos, line in enumerate(contents):
				if ignore_line_re.match(line):
					continue
				atom = line.split()[0]
				if atom.startswith("-"):
					# package.mask supports incrementals
					atom = atom[1:]
				if not isvalidatom(atom):
					continue
				new_atom = update_dbentry(update_cmd, atom)
				if atom != new_atom:
					contents[pos] = line.replace(atom, new_atom)
					update_files[x] = 1
					sys.stdout.write("p")
					sys.stdout.flush()

	protect_obj = ConfigProtect(
		config_root, protect, protect_mask)
	for x in update_files:
		updating_file = os.path.join(abs_user_config, x)
		if protect_obj.isprotected(updating_file):
			updating_file = new_protect_filename(updating_file)
		try:
			write_atomic(updating_file, "".join(file_contents[x]))
		except PortageException, e:
			writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
			writemsg("!!! An error occured while updating a config file:" + \
				" '%s'\n" % updating_file, noiselevel=-1)
			continue

def dep_transform(mydep, oldkey, newkey):
	if dep_getkey(mydep) == oldkey:
		return mydep.replace(oldkey, newkey, 1)
	return mydep
