# Copyright 2010-2011 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

__all__ = ["cpv_expand"]

from portage.exception import AmbiguousPackageName
from portage.localization import _
from portage.util import writemsg
from portage.versions import _pkgsplit

def cpv_expand(mycpv, mydb=None, use_cache=1, settings=None):
	"""Given a string (packagename or virtual) expand it into a valid
	cat/package string. Virtuals use the mydb to determine which provided
	virtual is a valid choice and defaults to the first element when there
	are no installed/available candidates."""
	myslash=mycpv.split("/")
	mysplit = _pkgsplit(myslash[-1])
	if settings is None:
		settings = globals()["settings"]
	if len(myslash)>2:
		# this is illegal case.
		mysplit=[]
		mykey=mycpv
	elif len(myslash)==2:
		if mysplit:
			mykey=myslash[0]+"/"+mysplit[0]
		else:
			mykey=mycpv

		# Since Gentoo stopped using old-style virtuals in
		# 2011, typically it's possible to avoid getvirtuals()
		# calls entirely. Therefore, only call getvirtuals()
		# if the atom category is "virtual" and cp_list()
		# returns nothing.
		if mykey.startswith("virtual/") and \
			hasattr(mydb, "cp_list") and \
			not mydb.cp_list(mykey, use_cache=use_cache):
				if hasattr(mydb, "vartree"):
					settings._populate_treeVirtuals_if_needed(mydb.vartree)
				virts = settings.getvirtuals().get(mykey)
				if virts:
					mykey_orig = mykey
					for vkey in virts:
						# The virtuals file can contain a versioned atom, so
						# it may be necessary to remove the operator and
						# version from the atom before it is passed into
						# dbapi.cp_list().
						if mydb.cp_list(vkey.cp):
							mykey = str(vkey)
							break
					if mykey == mykey_orig:
						mykey = str(virts[0])
			#we only perform virtual expansion if we are passed a dbapi
	else:
		#specific cpv, no category, ie. "foo-1.0"
		if mysplit:
			myp=mysplit[0]
		else:
			# "foo" ?
			myp=mycpv
		mykey=None
		matches=[]
		if mydb and hasattr(mydb, "categories"):
			for x in mydb.categories:
				if mydb.cp_list(x+"/"+myp,use_cache=use_cache):
					matches.append(x+"/"+myp)
		if len(matches) > 1:
			virtual_name_collision = False
			if len(matches) == 2:
				for x in matches:
					if not x.startswith("virtual/"):
						# Assume that the non-virtual is desired.  This helps
						# avoid the ValueError for invalid deps that come from
						# installed packages (during reverse blocker detection,
						# for example).
						mykey = x
					else:
						virtual_name_collision = True
			if not virtual_name_collision:
				# AmbiguousPackageName inherits from ValueError,
				# for backward compatibility with calling code
				# that already handles ValueError.
				raise AmbiguousPackageName(matches)
		elif matches:
			mykey=matches[0]

		if not mykey and not isinstance(mydb, list):
			if hasattr(mydb, "vartree"):
				settings._populate_treeVirtuals_if_needed(mydb.vartree)
			virts_p = settings.get_virts_p().get(myp)
			if virts_p:
				mykey = virts_p[0]
			#again, we only perform virtual expansion if we have a dbapi (not a list)
		if not mykey:
			mykey="null/"+myp
	if mysplit:
		if mysplit[2]=="r0":
			return mykey+"-"+mysplit[1]
		else:
			return mykey+"-"+mysplit[1]+"-"+mysplit[2]
	else:
		return mykey
