# Copyright 1999-2020 Gentoo Authors
# 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 a user might want to select multiple slots of a slotted
	package like gcc for example. 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 ebuild repository.
		#
		# 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:
		# Don't exclude slotted atoms for system packages from world, since
		# a user might want to select multiple slots of a slotted package like
		# gcc for example.
		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

