blob: 70ee782457ec3bee93e0794dd868b42b52bb73ba [file] [log] [blame]
# Copyright 2010-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
from __future__ import unicode_literals
__all__ = ["cpv_expand"]
import portage
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:
try:
settings = mydb.settings
except AttributeError:
settings = portage.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