Lines 3-15
Link Here
|
3 |
|
3 |
|
4 |
from __future__ import print_function |
4 |
from __future__ import print_function |
5 |
|
5 |
|
|
|
6 |
import io |
6 |
import re |
7 |
import re |
7 |
import portage |
8 |
import portage |
8 |
from portage import os |
9 |
from portage import os, _encodings |
9 |
from portage.dbapi.porttree import _parse_uri_map |
10 |
from portage.dbapi.porttree import _parse_uri_map |
|
|
11 |
from portage.dep import Atom |
12 |
from portage.exception import InvalidData |
10 |
from portage.localization import localized_size |
13 |
from portage.localization import localized_size |
11 |
from portage.output import bold, bold as white, darkgreen, green, red |
14 |
from portage.output import bold, bold as white, darkgreen, green, red |
12 |
from portage.util import writemsg_stdout |
15 |
from portage.util import writemsg_stdout |
|
|
16 |
from portage.versions import _pkg_str |
13 |
|
17 |
|
14 |
from _emerge.Package import Package |
18 |
from _emerge.Package import Package |
15 |
|
19 |
|
Lines 30-36
class search(object):
Link Here
|
30 |
The list of available and installed packages is created at object instantiation. |
34 |
The list of available and installed packages is created at object instantiation. |
31 |
This makes successive searches faster.""" |
35 |
This makes successive searches faster.""" |
32 |
self.settings = root_config.settings |
36 |
self.settings = root_config.settings |
33 |
self.vartree = root_config.trees["vartree"] |
|
|
34 |
self.spinner = spinner |
37 |
self.spinner = spinner |
35 |
self.verbose = verbose |
38 |
self.verbose = verbose |
36 |
self.searchdesc = searchdesc |
39 |
self.searchdesc = searchdesc |
Lines 41-49
class search(object):
Link Here
|
41 |
|
44 |
|
42 |
self._dbs = [] |
45 |
self._dbs = [] |
43 |
|
46 |
|
44 |
portdb = root_config.trees["porttree"].dbapi |
47 |
portdb = IndexedPortdb(root_config.trees["porttree"].dbapi) |
45 |
bindb = root_config.trees["bintree"].dbapi |
48 |
bindb = root_config.trees["bintree"].dbapi |
46 |
vardb = root_config.trees["vartree"].dbapi |
49 |
vardb = IndexedVardb(root_config.trees["vartree"].dbapi) |
47 |
|
50 |
|
48 |
if not usepkgonly and portdb._have_root_eclass_dir: |
51 |
if not usepkgonly and portdb._have_root_eclass_dir: |
49 |
self._dbs.append(portdb) |
52 |
self._dbs.append(portdb) |
Lines 53-58
class search(object):
Link Here
|
53 |
|
56 |
|
54 |
self._dbs.append(vardb) |
57 |
self._dbs.append(vardb) |
55 |
self._portdb = portdb |
58 |
self._portdb = portdb |
|
|
59 |
self._vardb = vardb |
56 |
|
60 |
|
57 |
def _spinner_update(self): |
61 |
def _spinner_update(self): |
58 |
if self.spinner: |
62 |
if self.spinner: |
Lines 97-103
class search(object):
Link Here
|
97 |
return {} |
101 |
return {} |
98 |
|
102 |
|
99 |
def _visible(self, db, cpv, metadata): |
103 |
def _visible(self, db, cpv, metadata): |
100 |
installed = db is self.vartree.dbapi |
104 |
installed = db is self._vardb |
101 |
built = installed or db is not self._portdb |
105 |
built = installed or db is not self._portdb |
102 |
pkg_type = "ebuild" |
106 |
pkg_type = "ebuild" |
103 |
if installed: |
107 |
if installed: |
Lines 208-213
class search(object):
Link Here
|
208 |
masked=1 |
212 |
masked=1 |
209 |
self.matches["pkg"].append([package,masked]) |
213 |
self.matches["pkg"].append([package,masked]) |
210 |
elif self.searchdesc: # DESCRIPTION searching |
214 |
elif self.searchdesc: # DESCRIPTION searching |
|
|
215 |
# Check for DESCRIPTION match first, so that we can skip |
216 |
# the expensive visiblity check if it doesn't match. |
217 |
full_package = portage.best( |
218 |
self._xmatch("match-all", package)) |
219 |
try: |
220 |
full_desc = self._aux_get( |
221 |
full_package, ["DESCRIPTION"])[0] |
222 |
except KeyError: |
223 |
portage.writemsg( |
224 |
"emerge: search: aux_get() failed, skipping\n", |
225 |
noiselevel=-1) |
226 |
continue |
227 |
if not self.searchre.search(full_desc): |
228 |
continue |
211 |
full_package = self._xmatch("bestmatch-visible", package) |
229 |
full_package = self._xmatch("bestmatch-visible", package) |
212 |
if not full_package: |
230 |
if not full_package: |
213 |
#no match found; we don't want to query description |
231 |
#no match found; we don't want to query description |
Lines 217-230
class search(object):
Link Here
|
217 |
continue |
235 |
continue |
218 |
else: |
236 |
else: |
219 |
masked=1 |
237 |
masked=1 |
220 |
try: |
238 |
|
221 |
full_desc = self._aux_get( |
239 |
self.matches["desc"].append((full_package, masked)) |
222 |
full_package, ["DESCRIPTION"])[0] |
|
|
223 |
except KeyError: |
224 |
print("emerge: search: aux_get() failed, skipping") |
225 |
continue |
226 |
if self.searchre.search(full_desc): |
227 |
self.matches["desc"].append([full_package,masked]) |
228 |
|
240 |
|
229 |
self.sdict = self.setconfig.getSets() |
241 |
self.sdict = self.setconfig.getSets() |
230 |
for setname in self.sdict: |
242 |
for setname in self.sdict: |
Lines 262-268
class search(object):
Link Here
|
262 |
bold(self.searchkey) + " ]\n") |
274 |
bold(self.searchkey) + " ]\n") |
263 |
msg.append("[ Applications found : " + \ |
275 |
msg.append("[ Applications found : " + \ |
264 |
bold(str(self.mlen)) + " ]\n\n") |
276 |
bold(str(self.mlen)) + " ]\n\n") |
265 |
vardb = self.vartree.dbapi |
277 |
vardb = self._vardb |
266 |
metadata_keys = set(Package.metadata_keys) |
278 |
metadata_keys = set(Package.metadata_keys) |
267 |
metadata_keys.update(["DESCRIPTION", "HOMEPAGE", "LICENSE", "SRC_URI"]) |
279 |
metadata_keys.update(["DESCRIPTION", "HOMEPAGE", "LICENSE", "SRC_URI"]) |
268 |
metadata_keys = tuple(metadata_keys) |
280 |
metadata_keys = tuple(metadata_keys) |
Lines 372-378
class search(object):
Link Here
|
372 |
# private interface |
384 |
# private interface |
373 |
# |
385 |
# |
374 |
def getInstallationStatus(self,package): |
386 |
def getInstallationStatus(self,package): |
375 |
installed_package = self.vartree.dep_bestmatch(package) |
387 |
installed_package = self._vardb.match(package) |
|
|
388 |
if installed_package: |
389 |
installed_package = installed_package[-1] |
390 |
else: |
391 |
installed_package = "" |
376 |
result = "" |
392 |
result = "" |
377 |
version = self.getVersion(installed_package,search.VERSION_RELEASE) |
393 |
version = self.getVersion(installed_package,search.VERSION_RELEASE) |
378 |
if len(version) > 0: |
394 |
if len(version) > 0: |
Lines 392-394
class search(object):
Link Here
|
392 |
result = "" |
408 |
result = "" |
393 |
return result |
409 |
return result |
394 |
|
410 |
|
395 |
- |
411 |
|
|
|
412 |
class IndexedPortdb(object): |
413 |
""" |
414 |
A portdbapi interface that uses a package description index to |
415 |
improve performance. If the description index is missing for a |
416 |
particular repository, then all metadata for that repository is |
417 |
obtained using the normal pordbapi.aux_get method. |
418 |
""" |
419 |
def __init__(self, portdb): |
420 |
self._portdb = portdb |
421 |
self.cpv_exists = portdb.cpv_exists |
422 |
self.getFetchMap = portdb.getFetchMap |
423 |
self.findname = portdb.findname |
424 |
self._aux_cache_keys = portdb._aux_cache_keys |
425 |
self._have_root_eclass_dir = portdb._have_root_eclass_dir |
426 |
self._cpv_sort_ascending = portdb._cpv_sort_ascending |
427 |
self._desc_cache = None |
428 |
self._cp_map = None |
429 |
|
430 |
def _init_index(self): |
431 |
cp_map = {} |
432 |
desc_cache = {} |
433 |
for repo_path in self._portdb.porttrees: |
434 |
outside_repo = os.path.join(self._portdb.depcachedir, |
435 |
repo_path.lstrip(os.sep)) |
436 |
for parent_dir in (repo_path, outside_repo): |
437 |
file_path = os.path.join(parent_dir, |
438 |
"metadata", "pkg_desc_index") |
439 |
|
440 |
try: |
441 |
with io.open(file_path, |
442 |
encoding=_encodings["repo.content"]) as f: |
443 |
for line in f: |
444 |
pkgs, desc = line.split(":", 1) |
445 |
desc = desc.strip() |
446 |
pkgs = pkgs.split(",") |
447 |
if not pkgs[0]: |
448 |
continue |
449 |
try: |
450 |
pkg = _pkg_str(pkgs[0]) |
451 |
except InvalidData: |
452 |
continue |
453 |
cp_list = cp_map.get(pkg.cp) |
454 |
if cp_list is None: |
455 |
cp_list = [] |
456 |
cp_map[pkg.cp] = cp_list |
457 |
cp_list.append(pkg) |
458 |
for ver in pkgs[1:]: |
459 |
try: |
460 |
cp_list.append( |
461 |
_pkg_str(pkg.cp + "-" + ver)) |
462 |
except InvalidData: |
463 |
pass |
464 |
for cpv in cp_list: |
465 |
desc_cache[cpv] = desc |
466 |
except IOError: |
467 |
pass |
468 |
else: |
469 |
break |
470 |
else: |
471 |
# No descriptions index was found, so populate |
472 |
# cp_map the slow way. |
473 |
for cp in self._portdb.cp_all(trees=[repo_path]): |
474 |
cp_list = cp_map.get(cp) |
475 |
if cp_list is None: |
476 |
cp_list = [] |
477 |
cp_map[cp] = cp_list |
478 |
for cpv in self._portdb.cp_list(cp, mytree=repo_path): |
479 |
if cpv not in cp_list: |
480 |
cp_list.append(_pkg_str(cpv)) |
481 |
|
482 |
self._desc_cache = desc_cache |
483 |
self._cp_map = cp_map |
484 |
|
485 |
def cp_all(self): |
486 |
if self._cp_map is None: |
487 |
self._init_index() |
488 |
return list(self._cp_map) |
489 |
|
490 |
def match(self, atom): |
491 |
if not isinstance(atom, Atom): |
492 |
atom = Atom(atom) |
493 |
cp_list = self._cp_map.get(atom.cp) |
494 |
if cp_list is None: |
495 |
return [] |
496 |
self._portdb._cpv_sort_ascending(cp_list) |
497 |
return portage.match_from_list(atom, cp_list) |
498 |
|
499 |
def aux_get(self, cpv, attrs, myrepo = None): |
500 |
if len(attrs) == 1 and attrs[0] == "DESCRIPTION": |
501 |
try: |
502 |
return [self._desc_cache[cpv]] |
503 |
except KeyError: |
504 |
pass |
505 |
return self._portdb.aux_get(cpv, attrs) |
506 |
|
507 |
|
508 |
class IndexedVardb(object): |
509 |
""" |
510 |
A vardbapi interface that sacrifices validation in order to |
511 |
improve performance. It takes advantage of vardbdbapi._aux_cache, |
512 |
which is backed by vardb_metadata.pickle. Since _aux_cache is |
513 |
not updated for every single merge/unmerge (see |
514 |
_aux_cache_threshold), the list of packages is obtained directly |
515 |
from the real vardbapi instance. If a package is missing from |
516 |
_aux_cache, then its metadata is obtained using the normal |
517 |
(validated) vardbapi.aux_get method. |
518 |
""" |
519 |
def __init__(self, vardb): |
520 |
self._vardb = vardb |
521 |
self._aux_cache_keys = vardb._aux_cache_keys |
522 |
self._cpv_sort_ascending = vardb._cpv_sort_ascending |
523 |
self._cp_map = {} |
524 |
self.cpv_exists = vardb.cpv_exists |
525 |
|
526 |
def cp_all(self): |
527 |
if self._cp_map: |
528 |
return list(self._cp_map) |
529 |
cp_map = self._cp_map |
530 |
for cpv in self._vardb.cpv_all(): |
531 |
cp = portage.cpv_getkey(cpv) |
532 |
if cp is not None: |
533 |
cp_list = cp_map.get(cp) |
534 |
if cp_list is None: |
535 |
cp_list = [] |
536 |
cp_map[cp] = cp_list |
537 |
cp_list.append(_pkg_str(cpv)) |
538 |
return list(cp_map) |
539 |
|
540 |
def match(self, atom): |
541 |
if not isinstance(atom, Atom): |
542 |
atom = Atom(atom) |
543 |
cp_list = self._cp_map.get(atom.cp) |
544 |
if cp_list is None: |
545 |
return [] |
546 |
self._vardb._cpv_sort_ascending(cp_list) |
547 |
return portage.match_from_list(atom, cp_list) |
548 |
|
549 |
def aux_get(self, cpv, attrs, myrepo = None): |
550 |
pkg_data = self._vardb._aux_cache["packages"].get(cpv) |
551 |
if not isinstance(pkg_data, tuple) or \ |
552 |
len(pkg_data) != 2 or \ |
553 |
not isinstance(pkg_data[1], dict): |
554 |
pkg_data = None |
555 |
if pkg_data is None: |
556 |
# It may be missing from _aux_cache due to |
557 |
# _aux_cache_threshold. |
558 |
return self._vardb.aux_get(cpv, attrs) |
559 |
metadata = pkg_data[1] |
560 |
return [metadata.get(k, "") for k in attrs] |