# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

import sys

from portage.dep import Atom, _repo_separator
from portage.exception import InvalidData

if sys.hexversion >= 0x3000000:
	_unicode = str
else:
	_unicode = unicode

def create_world_atom(pkg, args_set, root_config, before_install=False):
	"""Create a new atom for the world file if one does not exist.  If the
	argument atom is precise enough to identify a specific slot then a slot
	atom will be returned. Atoms that are in the system set may also be stored
	in world since system atoms can only match one slot while world atoms can
	be greedy with respect to slots.  Unslotted system packages will not be
	stored in world."""

	arg_atom = args_set.findAtomForPackage(pkg)
	if not arg_atom:
		return None
	cp = arg_atom.cp
	new_world_atom = cp
	if arg_atom.repo:
		new_world_atom += _repo_separator + arg_atom.repo
	sets = root_config.sets
	portdb = root_config.trees["porttree"].dbapi
	vardb = root_config.trees["vartree"].dbapi

	if arg_atom.repo is not None:
		repos = [arg_atom.repo]
	else:
		# Iterate over portdbapi.porttrees, since it's common to
		# tweak this attribute in order to adjust match behavior.
		repos = []
		for tree in portdb.porttrees:
			repos.append(portdb.repositories.get_name_for_location(tree))

	available_slots = set()
	for cpv in portdb.match(Atom(cp)):
		for repo in repos:
			try:
				available_slots.add(portdb._pkg_str(_unicode(cpv), repo).slot)
			except (KeyError, InvalidData):
				pass

	slotted = len(available_slots) > 1 or \
		(len(available_slots) == 1 and "0" not in available_slots)
	if not slotted:
		# check the vdb in case this is multislot
		available_slots = set(vardb._pkg_str(cpv, None).slot \
			for cpv in vardb.match(Atom(cp)))
		slotted = len(available_slots) > 1 or \
			(len(available_slots) == 1 and "0" not in available_slots)
	if slotted and arg_atom.without_repo != cp:
		# If the user gave a specific atom, store it as a
		# slot atom in the world file.
		slot_atom = pkg.slot_atom

		# For USE=multislot, there are a couple of cases to
		# handle here:
		#
		# 1) SLOT="0", but the real SLOT spontaneously changed to some
		#    unknown value, so just record an unslotted atom.
		#
		# 2) SLOT comes from an installed package and there is no
		#    matching SLOT in the portage tree.
		#
		# Make sure that the slot atom is available in either the
		# portdb or the vardb, since otherwise the user certainly
		# doesn't want the SLOT atom recorded in the world file
		# (case 1 above).  If it's only available in the vardb,
		# the user may be trying to prevent a USE=multislot
		# package from being removed by --depclean (case 2 above).

		mydb = portdb
		if not portdb.match(slot_atom):
			# SLOT seems to come from an installed multislot package
			mydb = vardb
		# If there is no installed package matching the SLOT atom,
		# it probably changed SLOT spontaneously due to USE=multislot,
		# so just record an unslotted atom.
		if vardb.match(slot_atom) or before_install:
			# Now verify that the argument is precise
			# enough to identify a specific slot.
			matches = mydb.match(arg_atom)
			matched_slots = set()
			if before_install:
				matched_slots.add(pkg.slot)
			if mydb is vardb:
				for cpv in matches:
					matched_slots.add(mydb._pkg_str(cpv, None).slot)
			else:
				for cpv in matches:
					for repo in repos:
						try:
							matched_slots.add(
								portdb._pkg_str(_unicode(cpv), repo).slot)
						except (KeyError, InvalidData):
							pass

			if len(matched_slots) == 1:
				new_world_atom = slot_atom
				if arg_atom.repo:
					new_world_atom += _repo_separator + arg_atom.repo

	if new_world_atom == sets["selected"].findAtomForPackage(pkg):
		# Both atoms would be identical, so there's nothing to add.
		return None
	if not slotted and not arg_atom.repo:
		# Unlike world atoms, system atoms are not greedy for slots, so they
		# can't be safely excluded from world if they are slotted.
		system_atom = sets["system"].findAtomForPackage(pkg)
		if system_atom:
			if not system_atom.cp.startswith("virtual/"):
				return None
			# System virtuals aren't safe to exclude from world since they can
			# match multiple old-style virtuals but only one of them will be
			# pulled in by update or depclean.
			providers = portdb.settings.getvirtuals().get(system_atom.cp)
			if providers and len(providers) == 1 and \
				providers[0].cp == arg_atom.cp:
				return None
	return new_world_atom

