diff --git a/pym/euscan/ebuild.py b/pym/euscan/ebuild.py new file mode 100644 index 0000000..2891e95 --- /dev/null +++ b/pym/euscan/ebuild.py @@ -0,0 +1,86 @@ +import os, sys, imp + +import portage +from portage.const import VDB_PATH +from portage import _encodings +from portage import _shell_quote +from portage import _unicode_decode +from portage import _unicode_encode + +# Stolen from the ebuild command +def package_from_ebuild(ebuild): + pf = None + if ebuild.endswith(".ebuild"): + pf = os.path.basename(ebuild)[:-7] + else: + return False + + if not os.path.isabs(ebuild): + mycwd = os.getcwd() + # Try to get the non-canonical path from the PWD evironment variable, + # since the canonical path returned from os.getcwd() may may be + # unusable in cases where the directory stucture is built from + # symlinks. + pwd = os.environ.get('PWD', '') + if sys.hexversion < 0x3000000: + pwd = _unicode_decode(pwd, encoding=_encodings['content'], + errors='strict') + if pwd and pwd != mycwd and \ + os.path.realpath(pwd) == mycwd: + mycwd = portage.normalize_path(pwd) + ebuild = os.path.join(mycwd, ebuild) + + ebuild = portage.normalize_path(ebuild) + # portdbapi uses the canonical path for the base of the portage tree, but + # subdirectories of the base can be built from symlinks (like crossdev + # does). + ebuild_portdir = os.path.realpath( + os.path.dirname(os.path.dirname(os.path.dirname(ebuild)))) + ebuild = os.path.join(ebuild_portdir, *ebuild.split(os.path.sep)[-3:]) + vdb_path = os.path.join(portage.settings['ROOT'], VDB_PATH) + + # Make sure that portdb.findname() returns the correct ebuild. + if ebuild_portdir != vdb_path and \ + ebuild_portdir not in portage.portdb.porttrees: + if sys.hexversion >= 0x3000000: + os.environ["PORTDIR_OVERLAY"] = \ + os.environ.get("PORTDIR_OVERLAY", "") + \ + " " + _shell_quote(ebuild_portdir) + else: + os.environ["PORTDIR_OVERLAY"] = \ + os.environ.get("PORTDIR_OVERLAY", "") + \ + " " + _unicode_encode(_shell_quote(ebuild_portdir), + encoding=_encodings['content'], errors='strict') + + portage.close_portdbapi_caches() + imp.reload(portage) + del portage.portdb.porttrees[1:] + if ebuild_portdir != portage.portdb.porttree_root: + portage.portdb.porttrees.append(ebuild_portdir) + + if not os.path.exists(ebuild): + return False + + ebuild_split = ebuild.split("/") + cpv = "%s/%s" % (ebuild_split[-3], pf) + + if not portage.catpkgsplit(cpv): + return False + + if ebuild.startswith(os.path.join(portage.root, portage.const.VDB_PATH)): + mytree = "vartree" + + portage_ebuild = portage.db[portage.root][mytree].dbapi.findname(cpv) + + if os.path.realpath(portage_ebuild) != ebuild: + return False + + else: + mytree = "porttree" + + portage_ebuild = portage.portdb.findname(cpv) + + if not portage_ebuild or portage_ebuild != ebuild: + return False + + return cpv diff --git a/pym/euscan/helpers.py b/pym/euscan/helpers.py index 7af055b..ab0fcda 100644 --- a/pym/euscan/helpers.py +++ b/pym/euscan/helpers.py @@ -3,10 +3,12 @@ import sys import re import pkg_resources import errno -import imp import urllib2 +import portage +from portage import dep + try: from urllib import robotparser from urllib import urlparse @@ -14,13 +16,6 @@ except ImportError: import robotparser import urlparse -import portage -from portage import dep -from portage.const import VDB_PATH -from portage import _encodings -from portage import _shell_quote -from portage import _unicode_decode -from portage import _unicode_encode from euscan import CONFIG, BLACKLIST_VERSIONS, ROBOTS_TXT_BLACKLIST_DOMAINS import euscan @@ -546,7 +541,6 @@ def generate_scan_paths(url): return steps - def parse_mirror(uri): from random import shuffle @@ -573,82 +567,3 @@ def parse_mirror(uri): return None return uri - - -# Stolen from ebuild -def query_from_ebuild(ebuild): - pf = None - if ebuild.endswith(".ebuild"): - pf = os.path.basename(ebuild)[:-7] - else: - return False - - if not os.path.isabs(ebuild): - mycwd = os.getcwd() - # Try to get the non-canonical path from the PWD evironment variable, - # since the canonical path returned from os.getcwd() may may be - # unusable in cases where the directory stucture is built from - # symlinks. - pwd = os.environ.get('PWD', '') - if sys.hexversion < 0x3000000: - pwd = _unicode_decode(pwd, encoding=_encodings['content'], - errors='strict') - if pwd and pwd != mycwd and \ - os.path.realpath(pwd) == mycwd: - mycwd = portage.normalize_path(pwd) - ebuild = os.path.join(mycwd, ebuild) - - ebuild = portage.normalize_path(ebuild) - # portdbapi uses the canonical path for the base of the portage tree, but - # subdirectories of the base can be built from symlinks (like crossdev - # does). - ebuild_portdir = os.path.realpath( - os.path.dirname(os.path.dirname(os.path.dirname(ebuild)))) - ebuild = os.path.join(ebuild_portdir, *ebuild.split(os.path.sep)[-3:]) - vdb_path = os.path.join(portage.settings['ROOT'], VDB_PATH) - - # Make sure that portdb.findname() returns the correct ebuild. - if ebuild_portdir != vdb_path and \ - ebuild_portdir not in portage.portdb.porttrees: - if sys.hexversion >= 0x3000000: - os.environ["PORTDIR_OVERLAY"] = \ - os.environ.get("PORTDIR_OVERLAY", "") + \ - " " + _shell_quote(ebuild_portdir) - else: - os.environ["PORTDIR_OVERLAY"] = \ - os.environ.get("PORTDIR_OVERLAY", "") + \ - " " + _unicode_encode(_shell_quote(ebuild_portdir), - encoding=_encodings['content'], errors='strict') - - portage.close_portdbapi_caches() - imp.reload(portage) - del portage.portdb.porttrees[1:] - if ebuild_portdir != portage.portdb.porttree_root: - portage.portdb.porttrees.append(ebuild_portdir) - - if not os.path.exists(ebuild): - return False - - ebuild_split = ebuild.split("/") - cpv = "%s/%s" % (ebuild_split[-3], pf) - - if not portage.catpkgsplit(cpv): - return False - - if ebuild.startswith(os.path.join(portage.root, portage.const.VDB_PATH)): - mytree = "vartree" - - portage_ebuild = portage.db[portage.root][mytree].dbapi.findname(cpv) - - if os.path.realpath(portage_ebuild) != ebuild: - return False - - else: - mytree = "porttree" - - portage_ebuild = portage.portdb.findname(cpv) - - if not portage_ebuild or portage_ebuild != ebuild: - return False - - return cpv diff --git a/pym/euscan/scan.py b/pym/euscan/scan.py index 17bd938..10628b5 100644 --- a/pym/euscan/scan.py +++ b/pym/euscan/scan.py @@ -2,20 +2,20 @@ import os import sys import portage - from portage.dbapi import porttree import gentoolkit.pprinter as pp from gentoolkit.query import Query +from gentoolkit.package import Package from gentoolkit.eclean.search import (port_settings) from euscan import CONFIG, BLACKLIST_PACKAGES from euscan import handlers from euscan import helpers +from euscan.ebuild import package_from_ebuild import euscan - def filter_versions(cp, versions): filtered = {} @@ -64,19 +64,31 @@ def scan_upstream_urls(cpv, urls): cp, ver, rev = portage.pkgsplit(cpv) return filter_versions(cp, versions) +# gentoolkit stores PORTDB, so even if we modify it to add an overlay +# it will still use the old dbapi +def reload_gentoolkit(): + import gentoolkit.package + import gentoolkit.query + + PORTDB = portage.db[portage.root]["porttree"].dbapi + if hasattr(gentoolkit.package, 'PORTDB'): + gentoolkit.package.PORTDB = PORTDB + if hasattr(gentoolkit.query, 'PORTDB'): + gentoolkit.query.PORTDB = PORTDB def scan_upstream(query): + matches = [] - # check if the query is an ebuild file. - # if it's a valid ebuild convert the filename in an euscan query - ebuild_query = helpers.query_from_ebuild(query) - if ebuild_query: - query = ebuild_query - - matches = Query(query).find( - include_masked=True, - in_installed=False - ) + if query.endswith(".ebuild"): + cpv = package_from_ebuild(query) + if cpv: + reload_gentoolkit() + matches = [Package(cpv)] + else: + matches = Query(query).find( + include_masked=True, + in_installed=False + ) if not matches: sys.stderr.write(