| Home | Trees | Indices | Help |
|
|---|
|
|
1 # -*- coding: utf-8 -*-
2 """
3
4 @author: Fabio Erculiani <lxnay@sabayonlinux.org>
5 @contact: lxnay@sabayonlinux.org
6 @copyright: Fabio Erculiani
7 @license: GPL-2
8
9 B{Entropy Source Package Manager "Portage" Plugin}.
10
11 """
12 from __future__ import with_statement
13 import os
14 import sys
15 import shutil
16 import tempfile
17 from entropy.const import etpConst, etpUi
18 from entropy.exceptions import FileNotFound, SPMError, InvalidDependString, \
19 InvalidData
20 from entropy.output import darkred, darkgreen, brown, darkblue, purple, red, \
21 bold
22 from entropy.i18n import _
23 from entropy.core.settings.base import SystemSettings
24 from entropy.misc import LogFile
25 from entropy.spm.plugins.skel import SpmPlugin
28 """
29 Entropy Package categories group representation
30 """
32 dict.__init__(self)
33
34 data = {
35 'office': {
36 'name': _("Office"),
37 'description': _("Applications used in office environments"),
38 'categories': [u'app-office', u'app-pda', u'app-mobilephone',
39 u'app-cdr', u'app-antivirus', u'app-laptop', u'mail-',
40 ],
41 },
42 'development': {
43 'name': _("Development"),
44 'description': _("Applications or system libraries"),
45 'categories': [u'dev-', u'sys-devel'],
46 },
47 'system': {
48 'name': _("System"),
49 'description': _("System applications or libraries"),
50 'categories': [u'sys-'],
51 },
52 'games': {
53 'name': _("Games"),
54 'description': _("Games, enjoy your spare time"),
55 'categories': [u'games-'],
56 },
57 'gnome': {
58 'name': _("GNOME Desktop"),
59 'description': \
60 _("Applications and libraries for the GNOME Desktop"),
61 'categories': [u'gnome-'],
62 },
63 'kde': {
64 'name': _("KDE Desktop"),
65 'description': \
66 _("Applications and libraries for the KDE Desktop"),
67 'categories': [u'kde-'],
68 },
69 'xfce': {
70 'name': _("XFCE Desktop"),
71 'description': \
72 _("Applications and libraries for the XFCE Desktop"),
73 'categories': [u'xfce-'],
74 },
75 'lxde': {
76 'name': _("LXDE Desktop"),
77 'description': \
78 _("Applications and libraries for the LXDE Desktop"),
79 'categories': [u'lxde-'],
80 },
81 'multimedia': {
82 'name': _("Multimedia"),
83 'description': \
84 _("Applications and libraries for Multimedia"),
85 'categories': [u'media-'],
86 },
87 'networking': {
88 'name': _("Networking"),
89 'description': \
90 _("Applications and libraries for Networking"),
91 'categories': [u'net-', u'www-'],
92 },
93 'science': {
94 'name': _("Science"),
95 'description': \
96 _("Scientific applications and libraries"),
97 'categories': [u'sci-'],
98 },
99 'x11': {
100 'name': _("X11"),
101 'description': \
102 _("Applications and libraries for X11"),
103 'categories': [u'x11-'],
104 },
105 }
106 self.update(data)
107
109
110 builtin_pkg_sets = [
111 "system","world","installed","module-rebuild",
112 "security","preserved-rebuild","live-rebuild",
113 "downgrade","unavailable"
114 ]
115
116 package_phases_map = {
117 'setup': 'setup',
118 'preinstall': 'preinst',
119 'postinstall': 'postinst',
120 'preremove': 'prerm',
121 'postremove': 'postrm',
122 'configure': 'config',
123 }
124
125 PLUGIN_API_VERSION = 0
126
127 SUPPORTED_MATCH_TYPES = [
128 "bestmatch-visible", "cp-list", "list-visible", "match-all",
129 "match-visible", "minimum-all", "minimum-visible"
130 ]
131
133 """Take a dependency structure as returned by paren_reduce or use_reduce
134 and generate an equivalent structure that has no redundant lists."""
138
140 if not src:
141 return dest
142 i = iter(src)
143 for x in i:
144 if isinstance(x, basestring):
145 if x == '||':
146 x = self._zap_parens(i.next(), [], disjunction=True)
147 if len(x) == 1:
148 dest.append(x[0])
149 else:
150 dest.append("||")
151 dest.append(x)
152 elif x.endswith("?"):
153 dest.append(x)
154 dest.append(self._zap_parens(i.next(), []))
155 else:
156 dest.append(x)
157 else:
158 if disjunction:
159 x = self._zap_parens(x, [])
160 if len(x) == 1:
161 dest.append(x[0])
162 else:
163 dest.append(x)
164 else:
165 self._zap_parens(x, dest)
166 return dest
167
168 import entropy.tools as entropyTools
170
171 mytxt = _("OutputInterface does not have an updateProgress method")
172 if not hasattr(OutputInterface,'updateProgress'):
173 raise AttributeError(mytxt)
174 elif not callable(OutputInterface.updateProgress):
175 raise AttributeError(mytxt)
176
177 # interface only needed OutputInterface functions
178 self.updateProgress = OutputInterface.updateProgress
179 self.askQuestion = OutputInterface.askQuestion
180 sys.path.append("/usr/lib/gentoolkit/pym")
181
182 # importing portage stuff
183 import portage
184 self.portage = portage
185 self.EAPI = 1
186 try:
187 import portage.const as portage_const
188 except ImportError:
189 import portage_const
190 if hasattr(portage_const, "EAPI"):
191 self.EAPI = portage_const.EAPI
192 self.portage_const = portage_const
193
194 from portage.versions import best
195 self._portage_best = best
196
197 try:
198 import portage.util as portage_util
199 except ImportError:
200 import portage_util
201 self.portage_util = portage_util
202
203 try:
204 import portage.sets as portage_sets
205 self.portage_sets = portage_sets
206 except ImportError:
207 self.portage_sets = None
208
209 try:
210 import glsa
211 self.glsa = glsa
212 except ImportError:
213 self.glsa = None
214
215 if hasattr(self.portage,'exception'):
216 self.portage_exception = self.portage.exception
217 else: # portage <2.2 workaround
218 self.portage_exception = Exception
219
220 @staticmethod
222 """
223 Return package groups available metadata (Spm categories are grouped
224 into macro categories called "groups").
225 """
226 return PortagePackageGroups()
227
229 """
230 Reimplemented from SpmPlugin class.
231 """
232 # return what's inside vartree because it's more complete
233 dbapi = self._get_portage_vartree().dbapi
234 if hasattr(dbapi, '_aux_cache_keys'):
235 return list(dbapi._aux_cache_keys)
236
237 sys.stderr.write("PortagePlugin: missing vardb._aux_cache_keys !\n")
238 return ["CHOST", "COUNTER", "DEPEND", "DESCRIPTION",
239 "EAPI", "HOMEPAGE", "IUSE", "KEYWORDS",
240 "LICENSE", "PDEPEND", "PROPERTIES", "PROVIDE", "RDEPEND",
241 "repository", "RESTRICT" , "SLOT", "USE"
242 ]
243
245 """
246 Reimplemented from SpmPlugin class.
247 """
248 if root is None:
249 root = etpConst['systemroot'] + os.path.sep
250 cache_path = self.portage_const.CACHE_PATH.lstrip(os.path.sep)
251 return os.path.join(root, cache_path)
252
254 """
255 Reimplemented from SpmPlugin class.
256 """
257 return self.portage.portdb.aux_get(package, [key])[0]
258
260 """
261 Reimplemented from SpmPlugin class.
262 """
263 ebuild_path = self.get_package_build_script_path(package)
264 if isinstance(ebuild_path, basestring):
265
266 clog_path = os.path.join(os.path.dirname(ebuild_path), "ChangeLog")
267 if os.access(clog_path, os.R_OK | os.F_OK):
268 with open(clog_path, "r") as clog_f:
269 return clog_f.read()
270
272 """
273 Reimplemented from SpmPlugin class.
274 """
275 return self.portage.portdb.findname(package)
276
278 """
279 Reimplemented from SpmPlugin class.
280 """
281 return os.path.join(self._get_vdb_path(root = root), package,
282 package.split("/")[-1] + etpConst['spm']['source_build_ext'])
283
285 """
286 Reimplemented from SpmPlugin class.
287 """
288 if root is None:
289 root = etpConst['systemroot'] + os.path.sep
290 vartree = self._get_portage_vartree(root = root)
291 return vartree.dbapi.aux_get(package, [key])[0]
292
294 """
295 Reimplemented from SpmPlugin class.
296 """
297 system = []
298 for package in self.portage.settings.packages:
299 pkgs = self.match_installed_package(package, match_all = True)
300 system.extend(pkgs)
301 system.extend(etpConst['spm']['system_packages'])
302 return system
303
305 """
306 Reimplemented from SpmPlugin class.
307 """
308 return self._get_portage_config(os.path.sep, os.path.sep).categories
309
311 """
312 Reimplemented from SpmPlugin class.
313 """
314 from xml.dom import minidom
315 data = {}
316 portdir = self.portage.settings['PORTDIR']
317 myfile = os.path.join(portdir,category,"metadata.xml")
318 if os.access(myfile,os.R_OK) and os.path.isfile(myfile):
319 doc = minidom.parse(myfile)
320 longdescs = doc.getElementsByTagName("longdescription")
321 for longdesc in longdescs:
322 data[longdesc.getAttribute("lang").strip()] = \
323 ' '.join([x.strip() for x in \
324 longdesc.firstChild.data.strip().split("\n")])
325 return data
326
328 """
329 Reimplemented from SpmPlugin class.
330 """
331 if not self.glsa:
332 return []
333 if security_property not in ['new','all','affected']:
334 return []
335
336 glsaconfig = self.glsa.checkconfig(
337 self.portage.config(clone=self.portage.settings))
338 completelist = self.glsa.get_glsa_list(
339 glsaconfig["GLSA_DIR"], glsaconfig)
340
341 glsalist = []
342 if security_property == "new":
343
344 checklist = []
345 if os.access(glsaconfig["CHECKFILE"], os.R_OK | os.F_OK):
346 with open(glsaconfig["CHECKFILE"], "r") as check_f:
347 checklist.extend([x.strip() for x in check_f.readlines()])
348 glsalist = [x for x in completelist if x not in checklist]
349
350 elif security_property == "all":
351 glsalist = completelist
352
353 elif security_property == "affected":
354
355 # maybe this should be todolist instead
356 for glsa_item in completelist:
357 try:
358 myglsa = self.glsa.Glsa(glsa_item, glsaconfig)
359 except (self.glsa.GlsaTypeException,
360 self.glsa.GlsaFormatException,):
361 continue
362
363 if not myglsa.isVulnerable():
364 continue
365
366 glsalist.append(glsa_item)
367
368 return glsalist
369
371 """
372 Reimplemented from SpmPlugin class.
373 """
374 if not self.glsa:
375 return {}
376
377 glsaconfig = self.glsa.checkconfig(
378 self.portage.config(clone=self.portage.settings))
379 try:
380 myglsa = self.glsa.Glsa(advisory_id, glsaconfig)
381 except (self.glsa.GlsaTypeException, self.glsa.GlsaFormatException):
382 return {}
383
384 mydict = {
385 'glsa_id': advisory_id,
386 'number': myglsa.nr,
387 'access': myglsa.access,
388 'title': myglsa.title,
389 'synopsis': myglsa.synopsis,
390 'announced': myglsa.announced,
391 'revised': myglsa.revised,
392 'bugs': myglsa.bugs,
393 'description': myglsa.description,
394 'resolution': myglsa.resolution,
395 'impact': myglsa.impact_text,
396 'impacttype': myglsa.impact_type,
397 'affected': myglsa.affected,
398 'background': myglsa.background,
399 'glsatype': myglsa.glsatype,
400 'packages': myglsa.packages,
401 'services': myglsa.services,
402 'product': myglsa.product,
403 'references': myglsa.references,
404 'workaround': myglsa.workaround,
405 }
406
407 status = "[U]"
408 if myglsa.isApplied():
409 status = "[A]"
410 elif myglsa.isVulnerable():
411 status = "[N]"
412 mydict['status'] = status
413
414 return mydict
415
421
423 """
424 Reimplemented from SpmPlugin class.
425 """
426 world_file = self.portage_const.WORLD_FILE
427 if root is None:
428 root = etpConst['systemroot'] + os.path.sep
429 return os.path.join(root, world_file)
430
432 """
433 Reimplemented from SpmPlugin class.
434 """
435 config_protect = self.portage.settings['CONFIG_PROTECT']
436 return [os.path.expandvars(x) for x in config_protect.split()]
437
439 """
440 Reimplemented from SpmPlugin class.
441 """
442 config_protect = self.portage.settings['CONFIG_PROTECT_MASK']
443 return [os.path.expandvars(x) for x in config_protect.split()]
444
446 """
447 Reimplemented from SpmPlugin class.
448 """
449 mirrors = []
450 if self.portage.thirdpartymirrors.has_key(mirror_name):
451 mirrors.extend(self.portage.thirdpartymirrors[mirror_name])
452 return mirrors
453
455 """
456 Reimplemented from SpmPlugin class.
457 """
458 root = etpConst['systemroot'] + os.path.sep
459 mydb = {}
460 mydb[root] = {}
461 mydb[root]['vartree'] = self._get_portage_vartree(root)
462 mydb[root]['porttree'] = self._get_portage_portagetree(root)
463 mydb[root]['bintree'] = self._get_portage_binarytree(root)
464 mydb[root]['virtuals'] = self.portage.settings.getvirtuals(root)
465
466 if etpUi['mute']:
467 pid = os.fork()
468 if pid > 0:
469 os.waitpid(pid, 0)
470 else:
471 log = LogFile(
472 level = etpConst['spmloglevel'],
473 filename = etpConst['spmlogfile'],
474 header = "[spm]"
475 )
476 old_stdout = sys.stdout
477 old_stderr = sys.stderr
478 sys.stdout = log
479 sys.stderr = log
480
481 self.portage._global_updates(mydb, {})
482
483 sys.stdout = old_stdout
484 sys.stderr = old_stderr
485 log.flush()
486 log.close()
487 os._exit(0)
488 else:
489 self.portage._global_updates(mydb, {}) # always force
490
492 """
493 Reimplemented from SpmPlugin class.
494 """
495 if match_type is None:
496 match_type = "bestmatch-visible"
497 elif match_type not in PortagePlugin.SUPPORTED_MATCH_TYPES:
498 raise KeyError
499
500 return self.portage.portdb.xmatch(match_type, package)
501
503 """
504 Reimplemented from SpmPlugin class.
505 """
506 if root is None:
507 root = etpConst['systemroot'] + os.path.sep
508
509 vartree = self._get_portage_vartree(root = root)
510 matches = vartree.dep_match(package) or []
511
512 if match_all:
513 return matches
514 elif matches:
515 return matches[-1]
516 return ''
517
519 """
520 Reimplemented from SpmPlugin class.
521 """
522 pkgcat, pkgname = package.split("/", 1)
523 if not os.path.isdir(file_save_path):
524 os.makedirs(file_save_path)
525 file_save_path += "/" + pkgname + etpConst['packagesext']
526 dbdir = os.path.join(self._get_vdb_path(), pkgcat, pkgname)
527
528 import tarfile
529 import stat
530 trees = self.portage.db["/"]
531 vartree = trees["vartree"]
532 dblnk = self.portage.dblink(pkgcat, pkgname, "/", vartree.settings,
533 treetype="vartree", vartree=vartree)
534 dblnk.lockdb()
535 tar = tarfile.open(file_save_path, "w:bz2")
536
537 contents = dblnk.getcontents()
538 paths = sorted(contents.keys())
539
540 for path in paths:
541 try:
542 exist = os.lstat(path)
543 except OSError:
544 continue # skip file
545 ftype = contents[path][0]
546 lpath = path
547 arcname = path[1:]
548 if 'dir' == ftype and \
549 not stat.S_ISDIR(exist.st_mode) and \
550 os.path.isdir(lpath):
551 lpath = os.path.realpath(lpath)
552 tarinfo = tar.gettarinfo(lpath, arcname)
553
554 if stat.S_ISREG(exist.st_mode):
555 tarinfo.mode = stat.S_IMODE(exist.st_mode)
556 tarinfo.type = tarfile.REGTYPE
557 f = open(path)
558 try:
559 tar.addfile(tarinfo, f)
560 finally:
561 f.close()
562 else:
563 tar.addfile(tarinfo)
564
565 tar.close()
566
567 # appending xpak informations
568 import entropy.xpak as xpak
569 tbz2 = xpak.tbz2(file_save_path)
570 tbz2.recompose(dbdir)
571
572 dblnk.unlockdb()
573
574 if os.access(file_save_path, os.F_OK):
575 return file_save_path
576
577 raise SPMError("SPMError: Spm:generate_package %s: %s %s" % (
578 _("error"),
579 file_save_path,
580 _("not found"),
581 )
582 )
583
585 """
586 Reimplemented from SpmPlugin class.
587 """
588 data = {}
589 system_settings = SystemSettings()
590
591 # fill package name and version
592 data['digest'] = self.entropyTools.md5sum(package_file)
593 data['signatures'] = {
594 'sha1': self.entropyTools.sha1(package_file),
595 'sha256': self.entropyTools.sha256(package_file),
596 'sha512': self.entropyTools.sha512(package_file),
597 }
598 data['datecreation'] = str(self.entropyTools.get_file_unix_mtime(
599 package_file))
600 data['size'] = str(self.entropyTools.get_file_size(package_file))
601
602 tmp_dir = tempfile.mkdtemp()
603 self.entropyTools.extract_xpak(package_file, tmp_dir)
604
605 # package injection status always false by default
606 # developer can change metadatum after this function
607 data['injected'] = False
608 data['branch'] = system_settings['repositories']['branch']
609
610 portage_entries = self._extract_pkg_metadata_generate_extraction_dict()
611 for item in portage_entries:
612
613 value = ''
614 try:
615
616 item_path = os.path.join(tmp_dir, portage_entries[item]['path'])
617 with open(item_path, "r") as item_f:
618 value = item_f.readline().strip().decode(
619 'raw_unicode_escape')
620
621 except IOError:
622 if portage_entries[item]['critical']:
623 raise
624 data[item] = value
625
626
627 # workout pf
628 pf_atom = os.path.join(data['category'], data['pf'])
629 pkgcat, pkgname, pkgver, pkgrev = self.entropyTools.catpkgsplit(
630 pf_atom)
631 if pkgrev != "r0":
632 pkgver += "-%s" % (pkgrev,)
633 data['name'] = pkgname
634 data['version'] = pkgver
635 # bye bye pf
636 del data['pf']
637
638 # setup spm_phases properly
639 spm_defined_phases_path = os.path.join(tmp_dir,
640 portage_entries['spm_phases']['path'])
641 if not os.path.isfile(spm_defined_phases_path):
642 # force to None, because metadatum can be '', which is valid
643 data['spm_phases'] = None
644
645 data['eclasses'] = set(data['eclasses'].split())
646 try:
647 data['counter'] = int(data['counter'])
648 except ValueError:
649 # -2 values will be insterted as incremental
650 # negative values into the database
651 data['counter'] = -2
652
653 data['keywords'] = [x.strip() for x in data['keywords'].split() \
654 if x.strip()]
655 if not data['keywords']:
656 # support for packages with no keywords
657 data['keywords'].insert(0, "")
658
659 data['keywords'] = set(data['keywords'])
660 needed_file = os.path.join(tmp_dir,
661 etpConst['spm']['xpak_entries']['needed'])
662
663 data['needed'] = self._extract_pkg_metadata_needed(needed_file)
664 data['needed_paths'] = self._extract_pkg_metadata_needed_paths(
665 data['needed'])
666
667 content_file = os.path.join(tmp_dir,
668 etpConst['spm']['xpak_entries']['contents'])
669 data['content'] = self._extract_pkg_metadata_content(content_file,
670 package_file)
671 data['disksize'] = self.entropyTools.sum_file_sizes(data['content'])
672
673 # [][][] Kernel dependent packages hook [][][]
674 data['versiontag'] = ''
675 kernelstuff = False
676 kernelstuff_kernel = False
677 for item in data['content']:
678 if item.startswith("/lib/modules/"):
679 kernelstuff = True
680 # get the version of the modules
681 kmodver = item.split("/lib/modules/")[1]
682 kmodver = kmodver.split("/")[0]
683
684 lp = kmodver.split("-")[-1]
685 if lp.startswith("r"):
686 kname = kmodver.split("-")[-2]
687 kver = kmodver.split("-")[0]+"-"+kmodver.split("-")[-1]
688 else:
689 kname = kmodver.split("-")[-1]
690 kver = kmodver.split("-")[0]
691 break
692
693 # validate the results above
694 if kernelstuff:
695 matchatom = "linux-%s-%s" % (kname,kver,)
696 if (matchatom == data['name']+"-"+data['version']):
697 kernelstuff_kernel = True
698
699 data['versiontag'] = kmodver
700 if not kernelstuff_kernel:
701 data['slot'] = kmodver # if you change this behaviour,
702 # you must change "reagent update"
703 # and "equo database gentoosync" consequentially
704
705 file_ext = etpConst['spm']['ebuild_file_extension']
706 ebuilds_in_path = [x for x in os.listdir(tmp_dir) if \
707 x.endswith(".%s" % (file_ext,))]
708
709 if not data['versiontag'] and ebuilds_in_path:
710 # has the user specified a custom package tag inside the ebuild
711 ebuild_path = os.path.join(tmp_dir, ebuilds_in_path[0])
712 data['versiontag'] = self._extract_pkg_metadata_ebuild_entropy_tag(
713 ebuild_path)
714
715 data['download'] = etpConst['packagesrelativepath'] + data['branch'] \
716 + "/"
717 data['download'] += self.entropyTools.create_package_filename(
718 data['category'], data['name'], data['version'], data['versiontag'])
719
720 data['trigger'] = ""
721 trigger_file = os.path.join(etpConst['triggersdir'], data['category'],
722 data['name'], etpConst['triggername'])
723 if os.access(trigger_file, os.F_OK | os.R_OK):
724 with open(trigger_file,"rb") as trig_f:
725 data['trigger'] = trig_f.read()
726
727 # Get Spm ChangeLog
728 pkgatom = "%s/%s-%s" % (data['category'], data['name'],
729 data['version'],)
730 try:
731 data['changelog'] = unicode(self.get_package_changelog(pkgatom),
732 'raw_unicode_escape')
733 except (UnicodeEncodeError, UnicodeDecodeError,), e:
734 sys.stderr.write("%s: %s, %s\n" % (
735 "changelog string conversion error", e,
736 package_file,)
737 )
738 data['changelog'] = None
739 except:
740 data['changelog'] = None
741
742 portage_metadata = self._calculate_dependencies(
743 data['iuse'], data['use'], data['license'], data['depend'],
744 data['rdepend'], data['pdepend'], data['provide'], data['sources']
745 )
746
747 data['provide'] = set(portage_metadata['PROVIDE'].split())
748 data['license'] = portage_metadata['LICENSE']
749 data['useflags'] = []
750 for my_use in portage_metadata['USE']:
751 if my_use in portage_metadata['USE_MASK']:
752 continue
753 if my_use in portage_metadata['USE_FORCE']:
754 data['useflags'].append(my_use)
755 continue
756 if my_use in portage_metadata['ENABLED_USE']:
757 data['useflags'].append(my_use)
758 else:
759 data['useflags'].append("-"+my_use)
760
761 # useflags must be a set, as returned by entropy.db.getPackageData
762 data['useflags'] = set(data['useflags'])
763 # sources must be a set, as returned by entropy.db.getPackageData
764 data['sources'] = set(portage_metadata['SRC_URI'].split())
765 data['dependencies'] = {}
766
767 for x in portage_metadata['RDEPEND'].split():
768 if x.startswith("!") or (x in ("(","||",")","")):
769 continue
770 data['dependencies'][x] = etpConst['spm']['(r)depend_id']
771
772 for x in portage_metadata['PDEPEND'].split():
773 if x.startswith("!") or (x in ("(","||",")","")):
774 continue
775 data['dependencies'][x] = etpConst['spm']['pdepend_id']
776
777 data['conflicts'] = [x.replace("!","") for x in \
778 portage_metadata['RDEPEND'].split() + \
779 portage_metadata['PDEPEND'].split() if \
780 x.startswith("!") and not x in ("(","||",")","")]
781
782 if (kernelstuff) and (not kernelstuff_kernel):
783 # add kname to the dependency
784 kern_dep_key = u"=sys-kernel/linux-"+kname+"-"+kver+"~-1"
785 data['dependencies'][kern_dep_key] = etpConst['spm']['(r)depend_id']
786
787 # Conflicting tagged packages support
788 # Needs Entropy Client System Settings Plugin,
789 # but since entropy.server loads entropy.client, it's completely
790 # fine as of now.
791 key = data['category'] + "/" + data['name']
792 plug_data = etpConst['system_settings_plugins_ids']
793 client_sysset_plg_id = plug_data['client_plugin']
794 client_data = system_settings.get(client_sysset_plg_id, {})
795 confl_data = None
796
797 if client_data:
798 repo_data = client_data['repositories']
799 confl_data = repo_data['conflicting_tagged_packages'].get(key)
800
801 if confl_data:
802 for conflict in confl_data:
803 data['conflicts'].append(conflict)
804
805 # conflicts must be a set, which is what is returned
806 # by entropy.db.getPackageData
807 data['conflicts'] = set(data['conflicts'])
808
809 # Get License text if possible
810 licenses_dir = os.path.join(self.get_setting('PORTDIR'), 'licenses')
811 data['licensedata'] = self._extract_pkg_metadata_license_data(
812 licenses_dir, data['license'])
813
814 data['mirrorlinks'] = self._extract_pkg_metadata_mirror_links(
815 data['sources'])
816
817 # write only if it's a systempackage
818 data['systempackage'] = False
819 system_packages = [self.entropyTools.dep_getkey(x) for x in \
820 self.get_system_packages()]
821 if data['category'] + "/" + data['name'] in system_packages:
822 data['systempackage'] = True
823
824 # write only if it's a systempackage
825 data['config_protect'] = ' '.join(self.get_merge_protected_paths())
826 data['config_protect_mask'] = ' '.join(
827 self.get_merge_protected_paths_mask())
828
829 log_dir = etpConst['logdir']+"/elog"
830 if not os.path.isdir(log_dir): os.makedirs(log_dir)
831 data['messages'] = self._extract_pkg_metadata_messages(log_dir,
832 data['category'], data['name'], data['version'])
833
834 # etpapi must be int, as returned by entropy.db.getPackageData
835 data['etpapi'] = int(etpConst['etpapi'])
836
837 # removing temporary directory
838 shutil.rmtree(tmp_dir, True)
839 if os.path.isdir(tmp_dir):
840 try:
841 os.remove(tmp_dir)
842 except OSError:
843 pass
844
845 # clear unused metadata
846 del data['use'], data['iuse'], data['depend'], data['pdepend'], \
847 data['rdepend']
848
849 return data
850
852 """
853 Reimplemented from SpmPlugin class.
854 """
855 result = self._unset_package_useflags(package, options)
856 if not result:
857 return False
858 return self._handle_new_useflags(package, options, "")
859
861 """
862 Reimplemented from SpmPlugin class.
863 """
864 result = self._unset_package_useflags(package, options)
865 if not result:
866 return False
867 return self._handle_new_useflags(package, options, "-")
868
870 """
871 Reimplemented from SpmPlugin class.
872 """
873 matched_atom = self.match_package(package)
874 if not matched_atom:
875 return {}
876 global_useflags = self._get_useflags()
877 use_force = self._get_useflags_force()
878 use_mask = self._get_useflags_mask()
879 package_use_useflags = self._get_package_use_useflags(package)
880
881 data = {}
882 data['use_force'] = use_force.copy()
883 data['use_mask'] = use_mask.copy()
884 data['global_use'] = global_useflags.split()
885
886 iuse = self.get_package_metadata(package, "IUSE")
887 if not isinstance(iuse, basestring):
888 iuse = ''
889 data['iuse'] = iuse.split()[:]
890 iuse = set()
891 for myiuse in data['iuse']:
892 if myiuse.startswith("+"):
893 myiuse = myiuse[1:]
894 iuse.add(myiuse)
895
896 use = [f for f in data['global_use'] + \
897 list(package_use_useflags['enabled']) if (f in iuse) \
898 and (f not in use_mask) and \
899 (f not in package_use_useflags['disabled'])]
900
901 use_disabled = [f for f in iuse if (f not in data['global_use']) \
902 and (f not in use_mask) and \
903 (f not in package_use_useflags['enabled'])]
904
905 data['use'] = use[:]
906 data['use_disabled'] = use_disabled[:]
907
908 matched_slot = self.get_package_metadata(matched_atom, "SLOT")
909 try:
910 inst_key = "%s:%s" % (
911 self.entropyTools.dep_getkey(package),
912 matched_slot,
913 )
914 installed_atom = self.match_installed_package(inst_key)
915 except self.portage_exception:
916 installed_atom = ''
917
918 if installed_atom:
919
920 # get its useflags
921 previous_iuse = self.get_installed_package_metadata(installed_atom,
922 "IUSE").split()
923 previous_use = self.get_installed_package_metadata(installed_atom,
924 "USE").split()
925
926 new_previous_iuse = set()
927 for myuse in previous_iuse:
928 if myuse.startswith("+"):
929 myuse = myuse[1:]
930 new_previous_iuse.add(myuse)
931 previous_iuse = list(new_previous_iuse)
932
933 inst_use = [f for f in previous_iuse if (f in previous_use) and \
934 (f not in use_mask)]
935 #inst_use_disabled = [f for f in previous_use if \
936 # (f not in previous_iuse) and (f not in use_mask)]
937
938 # check removed use
939 use_removed = []
940 for myuse in inst_use:
941 if myuse not in use:
942 use_removed.append(myuse)
943
944 # use not available
945 use_not_avail = []
946 for myuse in previous_iuse:
947 if (myuse not in iuse) and (myuse not in use_removed):
948 use_not_avail.append(myuse)
949
950 # check new use
951 t_use = []
952 for myuse in use:
953 if myuse not in inst_use:
954 myuse = "+%s*" % (myuse,)
955 t_use.append(myuse)
956 use = t_use
957
958 # check disabled use
959 t_use_disabled = []
960 for myuse in use_disabled:
961 if myuse in inst_use:
962 if myuse in use_removed+use_not_avail:
963 continue
964 myuse = "-%s*" % (myuse,)
965 else:
966 myuse = "-%s" % (myuse,)
967 t_use_disabled.append(myuse)
968 use_disabled = t_use_disabled
969
970 for myuse in use_removed:
971 use_disabled.append("(-%s*)" % (myuse,))
972 for myuse in use_not_avail:
973 use_disabled.append("(-%s)" % (myuse,))
974 else:
975 use_disabled = ["-"+x for x in use_disabled]
976
977 data['use_string'] = ' '.join(sorted(use)+sorted([x for x in \
978 use_disabled]))
979 data['use_string_colored'] = ' '.join(
980 sorted([darkred(x) for x in use if not x.startswith("+")] + \
981 [darkgreen(x) for x in use if x.startswith("+")]) + \
982 sorted([darkblue(x) for x in use_disabled if x.startswith("-")] + \
983 [brown(x) for x in use_disabled if x.startswith("(") and \
984 (x.find("*") == -1)] + \
985 [purple(x) for x in use_disabled if x.startswith("(") and \
986 (x.find("*") != -1)]
987 )
988 )
989
990 return data
991
993 """
994 Reimplemented from SpmPlugin class.
995 """
996 matched_atom = self.match_installed_package(package, root = root)
997 if not matched_atom:
998 return {}
999
1000 global_use = self.get_installed_package_metadata(matched_atom, "USE",
1001 root = root)
1002 use_mask = self._get_useflags_mask()
1003
1004 data = {}
1005 data['use_mask'] = use_mask.copy()
1006 data['global_use'] = global_use.split()
1007
1008 iuse = self.get_installed_package_metadata(matched_atom, "IUSE",
1009 root = root)
1010 if not isinstance(iuse, basestring):
1011 iuse = ''
1012 data['iuse'] = iuse.split()[:]
1013 iuse = set()
1014 for myiuse in data['iuse']:
1015 if myiuse.startswith("+"):
1016 myiuse = myiuse[1:]
1017 iuse.add(myiuse)
1018
1019 use = [f for f in data['global_use'] if (f in iuse) and \
1020 (f not in use_mask)]
1021 use_disabled = [f for f in iuse if (f not in data['global_use']) and \
1022 (f not in use_mask)]
1023 data['use'] = use[:]
1024 data['use_disabled'] = use_disabled[:]
1025
1026 data['use_string'] = ' '.join(sorted(use)+sorted([x for x in \
1027 use_disabled]))
1028 data['use_string_colored'] = ' '.join(
1029 sorted([darkred(x) for x in use if not x.startswith("+")] + \
1030 [darkgreen(x) for x in use if x.startswith("+")]) + \
1031 sorted([darkblue(x) for x in use_disabled if x.startswith("-")] + \
1032 [brown(x) for x in use_disabled if x.startswith("(") and \
1033 (x.find("*") == -1)] + \
1034 [purple(x) for x in use_disabled if x.startswith("(") and \
1035 (x.find("*") != -1)]
1036 )
1037 )
1038 return data
1039
1041 """
1042 Reimplemented from SpmPlugin class.
1043 """
1044 if root is None:
1045 root = etpConst['systemroot'] + os.path.sep
1046 mytree = self._get_portage_vartree(root)
1047
1048 cat, pkgv = package.split("/")
1049 return sorted(self.portage.dblink(cat, pkgv, root,
1050 self.portage.settings).getcontents())
1051
1053 """
1054 Reimplemented from SpmPlugin class.
1055 """
1056 if categories is None:
1057 categories = []
1058
1059 root = etpConst['systemroot'] + os.path.sep
1060 mysettings = self._get_portage_config(os.path.sep, root)
1061 portdb = self.portage.portdbapi(mysettings["PORTDIR"],
1062 mysettings = mysettings)
1063
1064 cps = portdb.cp_all()
1065 visibles = set()
1066 for cp in cps:
1067 if categories and cp.split("/")[0] not in categories:
1068 continue
1069
1070 # get slots
1071 slots = set()
1072 atoms = self.match_package(cp, match_type = "match-visible")
1073 if atoms:
1074 for atom in atoms:
1075 slots.add(portdb.aux_get(atom, ["SLOT"])[0])
1076 for slot in slots:
1077 visibles.add(cp+":"+slot)
1078
1079 # now match visibles
1080 available = set()
1081 for visible in visibles:
1082
1083 match = self.match_package(visible)
1084 if not match:
1085 continue
1086
1087 if filter_reinstalls:
1088 installed = self.match_installed_package(visible)
1089 if installed != match:
1090 available.add(match)
1091 else:
1092 available.add(match)
1093
1094 return available
1095
1097 """
1098 Reimplemented from SpmPlugin class.
1099 """
1100 vartree = self._get_portage_vartree(root = root)
1101 packages = vartree.dbapi.cpv_all()
1102 if not categories:
1103 return packages
1104
1105 def catfilter(pkg):
1106 if pkg.split("/", 1)[0] in categories:
1107 return True
1108 return False
1109
1110 return filter(catfilter, packages)
1111
1113 """
1114 Reimplemented from SpmPlugin class.
1115 """
1116 config = self._get_set_config()
1117 if config == None:
1118 return {}
1119
1120 mysets = config.getSets()
1121 if not builtin_sets:
1122 builtin_pkg_sets = [x for x in PortagePlugin.builtin_pkg_sets if \
1123 x in mysets]
1124 for pkg_set in builtin_pkg_sets:
1125 mysets.pop(pkg_set)
1126
1127 return dict((x, y.getAtoms(),) for x, y in mysets.items())
1128
1130 """
1131 Reimplemented from SpmPlugin class.
1132 """
1133 if root is None:
1134 root = etpConst['systemroot'] + os.path.sep
1135
1136 vartree = self._get_portage_vartree(root)
1137 dbbuild = self.get_installed_package_build_script_path(package,
1138 root = root)
1139
1140 counter_dir = os.path.dirname(dbbuild)
1141 counter_name = etpConst['spm']['xpak_entries']['counter']
1142 counter_path = os.path.join(counter_dir, counter_name)
1143
1144 if not os.access(counter_dir, os.W_OK):
1145 raise SPMError("SPM package directory not found")
1146
1147 with open(counter_path, "w") as count_f:
1148 new_counter = vartree.dbapi.counter_tick(root, mycpv = package)
1149 count_f.write(str(new_counter))
1150 count_f.flush()
1151
1152 return new_counter
1153
1155 """
1156 Reimplemented from SpmPlugin class.
1157 """
1158 if not isinstance(paths, (list, set, frozenset, dict, tuple,)):
1159 raise AttributeError("iterable needed")
1160 root = etpConst['systemroot'] + os.path.sep
1161 mytree = self._get_portage_vartree(root)
1162 packages = mytree.dbapi.cpv_all()
1163 matches = {}
1164
1165 for package in packages:
1166 cat, pkgv = package.split("/")
1167 content = self.portage.dblink(cat, pkgv, root,
1168 self.portage.settings).getcontents()
1169
1170 if exact_match:
1171 for filename in paths:
1172 if filename in content:
1173 myslot = self.get_installed_package_metadata(package,
1174 "SLOT")
1175 obj = matches.setdefault((package, myslot,), set())
1176 obj.add(filename)
1177 else:
1178 for filename in paths:
1179 for myfile in content:
1180 if myfile.find(filename) == -1:
1181 continue
1182 myslot = self.get_installed_package_metadata(package,
1183 "SLOT")
1184 obj = matches.setdefault((package, myslot,), set())
1185 obj.add(filename)
1186
1187 return matches
1188
1189 - def _portage_doebuild(self, myebuild, mydo, tree, cpv,
1190 portage_tmpdir = None, licenses = None):
1191 # myebuild = path/to/ebuild.ebuild with a valid unpacked xpak metadata
1192 # tree = "bintree"
1193 # cpv = atom
1194 # mydbapi = portage.fakedbapi(settings=portage.settings)
1195 # vartree = portage.vartree(root=myroot)
1196
1197 if licenses is None:
1198 licenses = []
1199
1200 oldsystderr = sys.stderr
1201 dev_null = open("/dev/null","w")
1202 if not etpUi['debug']:
1203 sys.stderr = dev_null
1204
1205 ### SETUP ENVIRONMENT
1206 # if mute, supress portage output
1207 domute = False
1208 if etpUi['mute']:
1209 domute = True
1210 oldsysstdout = sys.stdout
1211 sys.stdout = dev_null
1212
1213 root = etpConst['systemroot'] + os.path.sep
1214
1215 # old way to avoid loop of deaths for entropy portage hooks
1216 os.environ["SKIP_EQUO_SYNC"] = "1"
1217
1218 # load metadata
1219 myebuilddir = os.path.dirname(myebuild)
1220 keys = self.portage.auxdbkeys
1221 metadata = {}
1222
1223 for key in keys:
1224 mykeypath = os.path.join(myebuilddir,key)
1225 if os.path.isfile(mykeypath) and os.access(mykeypath,os.R_OK):
1226 f = open(mykeypath,"r")
1227 metadata[key] = f.readline().strip()
1228 f.close()
1229
1230 ### END SETUP ENVIRONMENT
1231
1232 # find config
1233 mysettings = self._get_portage_config(os.path.sep, root)
1234 mysettings['EBUILD_PHASE'] = mydo
1235
1236 # crappy, broken, ebuilds, put accept_license eutils call
1237 # in pkg_setup, when environment variables are not setup yet
1238 # WARNING WARNING WARNING:
1239 # if some other hook fails for other reasons, it's because
1240 # it may miss env variable here.
1241 mysettings['LICENSE'] = str(' '.join(licenses))
1242 if licenses:
1243 # we already do this early
1244 mysettings["ACCEPT_LICENSE"] = mysettings['LICENSE']
1245 mysettings.backup_changes("ACCEPT_LICENSE")
1246
1247 mysettings['EAPI'] = "0"
1248 if metadata.has_key('EAPI'):
1249 mysettings['EAPI'] = metadata['EAPI']
1250
1251 # workaround for scripts asking for user intervention
1252 mysettings['ROOT'] = root
1253 mysettings['CD_ROOT'] = "/tmp"
1254
1255 mysettings.backup_changes("EAPI")
1256 mysettings.backup_changes("LICENSE")
1257 mysettings.backup_changes("EBUILD_PHASE")
1258 mysettings.backup_changes("ROOT")
1259 mysettings.backup_changes("CD_ROOT")
1260
1261 try: # this is a >portage-2.1.4_rc11 feature
1262 mysettings._environ_whitelist = set(mysettings._environ_whitelist)
1263 # put our vars into whitelist
1264 mysettings._environ_whitelist.add("SKIP_EQUO_SYNC")
1265 mysettings._environ_whitelist.add("ACCEPT_LICENSE")
1266 mysettings._environ_whitelist.add("CD_ROOT")
1267 mysettings._environ_whitelist.add("ROOT")
1268 mysettings._environ_whitelist = frozenset(mysettings._environ_whitelist)
1269 except (AttributeError,):
1270 self.log_message(self.entropyTools.get_traceback())
1271
1272 cpv = str(cpv)
1273 mysettings.setcpv(cpv)
1274 portage_tmpdir_created = False # for pkg_postrm, pkg_prerm
1275
1276 if portage_tmpdir is None:
1277 portage_tmpdir = self.entropyTools.get_random_temp_file()
1278
1279 if portage_tmpdir:
1280 if not os.path.isdir(portage_tmpdir):
1281 os.makedirs(portage_tmpdir)
1282 portage_tmpdir_created = True
1283 mysettings['PORTAGE_TMPDIR'] = str(portage_tmpdir)
1284 mysettings.backup_changes("PORTAGE_TMPDIR")
1285
1286 # create FAKE ${PORTDIR} directory and licenses subdir
1287 portdir = os.path.join(portage_tmpdir, "portdir")
1288 portdir_lic = os.path.join(portdir, "licenses")
1289 if not os.path.isdir(portdir):
1290 os.mkdir(portdir) # portage_tmpdir must be available!
1291 # create licenses subdir
1292 if not os.path.isdir(portdir_lic):
1293 os.mkdir(portdir_lic)
1294
1295 # set fake PORTDIR
1296 old_portdir = mysettings["PORTDIR"][:]
1297 mysettings["PORTDIR"] = portdir
1298 mysettings.backup_changes("PORTDIR")
1299
1300 ### WORKAROUND for buggy check_license() in eutils.eclass
1301 ### that looks for file availability before considering
1302 ### ACCEPT_LICENSE
1303 for lic in licenses:
1304 lic_path = os.path.join(portdir_lic, lic)
1305 if not os.access(lic_path, os.F_OK):
1306 lic_f = open(lic_path, "w")
1307 lic_f.close()
1308
1309 mydbapi = self.portage.fakedbapi(settings=mysettings)
1310 mydbapi.cpv_inject(cpv, metadata = metadata)
1311
1312 # cached vartree class
1313 vartree = self._get_portage_vartree(root = root)
1314
1315 try:
1316 rc = self.portage.doebuild(
1317 myebuild = str(myebuild),
1318 mydo = str(mydo),
1319 myroot = root,
1320 tree = tree,
1321 mysettings = mysettings,
1322 mydbapi = mydbapi,
1323 vartree = vartree,
1324 use_cache = 0
1325 )
1326 except:
1327 self.log_message(self.entropyTools.get_traceback())
1328 raise
1329
1330 # if mute, restore old stdout/stderr
1331 if domute:
1332 sys.stdout = oldsysstdout
1333
1334 sys.stderr = oldsystderr
1335 dev_null.close()
1336
1337 if portage_tmpdir_created:
1338 shutil.rmtree(portage_tmpdir, True)
1339
1340 # reset PORTDIR back to its old path
1341 # for security !
1342 mysettings["PORTDIR"] = old_portdir
1343 mysettings.backup_changes("PORTDIR")
1344
1345 del mydbapi
1346 del metadata
1347 del keys
1348 return rc
1349
1350 - def execute_package_phase(self, package, build_script_path, phase_name,
1351 work_dir = None, licenses_accepted = None):
1352 """
1353 Reimplemented from SpmPlugin class.
1354 """
1355 if licenses_accepted is None:
1356 licenses_accepted = []
1357
1358 portage_phase = PortagePlugin.package_phases_map[phase_name]
1359 return self._portage_doebuild(build_script_path, portage_phase,
1360 "bintree", package, work_dir, licenses_accepted)
1361
1363 """
1364 Reimplemented from SpmPlugin class.
1365 """
1366 atomsfound = set()
1367 category = package_metadata['category']
1368 key = category + "/" + package_metadata['name']
1369 spm_package = key + "-" + package_metadata['version']
1370
1371 build = self.get_installed_package_build_script_path(spm_package)
1372 pkg_dir = os.path.dirname(build)
1373 cat_dir = os.path.dirname(pkg_dir)
1374
1375 if os.path.isdir(cat_dir):
1376 my_findings = [os.path.join(category, x) for x in \
1377 os.listdir(cat_dir)]
1378 # filter by key
1379 real_findings = [x for x in my_findings if \
1380 key == self.entropyTools.dep_getkey(x)]
1381 atomsfound.update(real_findings)
1382
1383 myslot = package_metadata['slot']
1384 for xatom in atomsfound:
1385
1386 if self.get_installed_package_metadata(xatom, "SLOT") != myslot:
1387 continue
1388
1389 mybuild = self.get_installed_package_build_script_path(xatom)
1390 remove_path = os.path.dirname(mybuild)
1391 shutil.rmtree(remove_path, True)
1392
1393 # we now install it
1394 xpak_rel_path = etpConst['entropyxpakdatarelativepath']
1395 proposed_xpak_dir = os.path.join(package_metadata['xpakpath'],
1396 xpak_rel_path)
1397
1398 counter = -1
1399 if (package_metadata['xpakstatus'] != None) and \
1400 os.path.isdir(proposed_xpak_dir) or package_metadata['merge_from']:
1401
1402 copypath = proposed_xpak_dir
1403 if package_metadata['merge_from']:
1404 copypath = package_metadata['xpakdir']
1405 if not os.path.isdir(copypath):
1406 return 0
1407
1408 if not os.path.isdir(cat_dir):
1409 os.makedirs(cat_dir, 0755)
1410 if os.path.isdir(pkg_dir):
1411 shutil.rmtree(pkg_dir)
1412
1413 try:
1414 shutil.copytree(copypath, pkg_dir)
1415 except (IOError,), e:
1416 mytxt = "%s: %s: %s: %s" % (red(_("QA")),
1417 brown(_("Cannot update Portage database to destination")),
1418 purple(pkg_dir),e,)
1419 self.updateProgress(
1420 mytxt,
1421 importance = 1,
1422 type = "warning",
1423 header = darkred(" ## ")
1424 )
1425
1426 try:
1427 counter = self.assign_uid_to_installed_package(spm_package)
1428 except SPMError, err:
1429 mytxt = "%s: %s [%s]" % (
1430 brown(_("SPM uid update error")), pkg_dir, err,
1431 )
1432 self.updateProgress(
1433 red("QA: ") + mytxt,
1434 importance = 1,
1435 type = "warning",
1436 header = darkred(" ## ")
1437 )
1438 counter = -1
1439
1440 user_inst_source = etpConst['install_sources']['user']
1441 if package_metadata['install_source'] != user_inst_source:
1442 # only user selected packages in Portage world file
1443 return counter
1444
1445 myslot = package_metadata['slot'][:]
1446 if (package_metadata['versiontag'] == package_metadata['slot']) \
1447 and package_metadata['versiontag']:
1448 # usually kernel packages
1449 myslot = "0"
1450
1451 keyslot = key+":"+myslot
1452 world_file = self.get_user_installed_packages_file()
1453 world_dir = os.path.dirname(world_file)
1454 world_atoms = set()
1455
1456 if os.access(world_file, os.R_OK | os.F_OK):
1457 with open(world_file, "r") as world_f:
1458 world_atoms |= set((x.strip() for x in world_f.readlines() if \
1459 x.strip()))
1460
1461 try:
1462
1463 if keyslot not in world_atoms and \
1464 os.access(world_dir, os.W_OK) and \
1465 self.entropyTools.istextfile(world_file):
1466
1467 world_atoms.discard(key)
1468 world_atoms.add(keyslot)
1469 world_file_tmp = world_file+".entropy_inst"
1470
1471 with open(world_file_tmp, "w") as world_f:
1472 for item in sorted(world_atoms):
1473 world_f.write(item + "\n")
1474 world_f.flush()
1475
1476 os.rename(world_file_tmp, world_file)
1477
1478 except (UnicodeDecodeError, UnicodeEncodeError,), e:
1479
1480 mytxt = "%s: %s" % (
1481 brown(_("Cannot update SPM installed pkgs file")), world_file,
1482 )
1483 self.updateProgress(
1484 red("QA: ") + mytxt + ": " + unicode(e),
1485 importance = 1,
1486 type = "warning",
1487 header = darkred(" ## ")
1488 )
1489
1490 return counter
1491
1493 """
1494 Reimplemented from SpmPlugin class.
1495 """
1496 atom = self.entropyTools.remove_tag(package_metadata['removeatom'])
1497 remove_build = self.get_installed_package_build_script_path(atom)
1498 remove_path = os.path.dirname(remove_build)
1499 key = self.entropyTools.dep_getkey(atom)
1500
1501 others_installed = self.match_installed_package(key, match_all = True)
1502 if atom in others_installed:
1503 others_installed.remove(atom)
1504
1505 # Support for tagged packages
1506 slot = package_metadata['slot']
1507 tag = package_metadata['versiontag']
1508 if (tag == slot) and tag:
1509 slot = "0"
1510
1511 def do_rm_path_atomic(xpath):
1512 for my_el in os.listdir(xpath):
1513 my_el = os.path.join(xpath, my_el)
1514 try:
1515 os.remove(my_el)
1516 except OSError:
1517 pass
1518 try:
1519 os.rmdir(xpath)
1520 except OSError:
1521 pass
1522
1523 if os.path.isdir(remove_path):
1524 do_rm_path_atomic(remove_path)
1525
1526 # also remove parent directory if empty
1527 category_path = os.path.dirname(remove_path)
1528 if os.path.isdir(category_path):
1529 if not os.listdir(category_path):
1530 try:
1531 os.rmdir(category_path)
1532 except OSError:
1533 pass
1534
1535 if others_installed:
1536
1537 for myatom in others_installed:
1538 myslot = self.get_installed_package_metadata(myatom, "SLOT")
1539 if myslot != slot:
1540 continue
1541 mybuild = self.get_installed_package_build_script_path(myatom)
1542 mydir = os.path.dirname(mybuild)
1543 if not os.path.isdir(mydir):
1544 continue
1545 do_rm_path_atomic(mydir)
1546
1547 return 0
1548
1549 # otherwise update Portage world file
1550 world_file = self.get_user_installed_packages_file()
1551 world_file_tmp = world_file + ".entropy.tmp"
1552 if os.access(world_file, os.W_OK | os.F_OK):
1553
1554 new = open(world_file_tmp,"w")
1555 old = open(world_file,"r")
1556 line = old.readline()
1557
1558 while line:
1559
1560 if line.find(key) != -1:
1561 line = old.readline()
1562 continue
1563 if line.find(key+":"+slot) != -1:
1564 line = old.readline()
1565 continue
1566 new.write(line)
1567 line = old.readline()
1568
1569 new.flush()
1570 new.close()
1571 old.close()
1572 os.rename(world_file_tmp, world_file)
1573
1574 return 0
1575
1577 """
1578 Reimplemented from SpmPlugin class.
1579 """
1580 atom = package_metadata['key'] + "-" + package_metadata['version']
1581 myebuild = self.get_installed_package_build_script_path(atom)
1582
1583 if not os.access(myebuild, os.R_OK | os.F_OK):
1584 # cannot find ebuild ! ouch!
1585 return 2
1586
1587 try:
1588 rc = self.execute_package_phase(atom, myebuild,
1589 "configure",
1590 licenses_accepted = package_metadata['accept_license']
1591 )
1592 if rc == 1:
1593 return 3
1594
1595 except Exception, err:
1596
1597 self.entropyTools.print_traceback()
1598 mytxt = "%s: %s %s." % (
1599 bold(_("QA")),
1600 brown(_("Cannot run SPM configure phase for")),
1601 bold(str(atom)),
1602 )
1603 mytxt2 = "%s: %s, %s" % (
1604 bold(_("Error")),
1605 type(Exception),
1606 err,
1607 )
1608 for txt in (mytxt, mytxt2,):
1609 self.updateProgress(
1610 txt,
1611 importance = 0,
1612 header = red(" ## ")
1613 )
1614 return 1
1615
1616 return 0
1617
1619
1620 if root is None:
1621 root = etpConst['systemroot'] + os.path.sep
1622
1623 if not etpConst['spm']['cache'].has_key('portage'):
1624 etpConst['spm']['cache']['portage'] = {}
1625 if not etpConst['spm']['cache']['portage'].has_key('vartree'):
1626 etpConst['spm']['cache']['portage']['vartree'] = {}
1627
1628 cached = etpConst['spm']['cache']['portage']['vartree'].get(root)
1629 if cached != None:
1630 return cached
1631
1632 try:
1633 mytree = self.portage.vartree(root=root)
1634 except Exception, e:
1635 raise SPMError("SPMError: %s: %s" % (Exception,e,))
1636 etpConst['spm']['cache']['portage']['vartree'][root] = mytree
1637 return mytree
1638
1640
1641 if not etpConst['spm']['cache'].has_key('portage'):
1642 etpConst['spm']['cache']['portage'] = {}
1643 if not etpConst['spm']['cache']['portage'].has_key('portagetree'):
1644 etpConst['spm']['cache']['portage']['portagetree'] = {}
1645
1646 cached = etpConst['spm']['cache']['portage']['portagetree'].get(root)
1647 if cached != None:
1648 return cached
1649
1650 try:
1651 mytree = self.portage.portagetree(root=root)
1652 except Exception, e:
1653 raise SPMError("SPMError: %s: %s" % (Exception,e,))
1654 etpConst['spm']['cache']['portage']['portagetree'][root] = mytree
1655 return mytree
1656
1658
1659 if not etpConst['spm']['cache'].has_key('portage'):
1660 etpConst['spm']['cache']['portage'] = {}
1661 if not etpConst['spm']['cache']['portage'].has_key('binarytree'):
1662 etpConst['spm']['cache']['portage']['binarytree'] = {}
1663
1664 cached = etpConst['spm']['cache']['portage']['binarytree'].get(root)
1665 if cached != None:
1666 return cached
1667
1668 pkgdir = root+self.portage.settings['PKGDIR']
1669 try:
1670 mytree = self.portage.binarytree(root,pkgdir)
1671 except Exception, e:
1672 raise SPMError("SPMError: %s: %s" % (Exception,e,))
1673 etpConst['spm']['cache']['portage']['binarytree'][root] = mytree
1674 return mytree
1675
1677
1678 if use_cache:
1679 if not etpConst['spm']['cache'].has_key('portage'):
1680 etpConst['spm']['cache']['portage'] = {}
1681 if not etpConst['spm']['cache']['portage'].has_key('config'):
1682 etpConst['spm']['cache']['portage']['config'] = {}
1683
1684 cached = etpConst['spm']['cache']['portage']['config'].get((config_root,root))
1685 if cached != None:
1686 return cached
1687
1688 try:
1689 mysettings = self.portage.config(config_root = config_root, target_root = root, config_incrementals = self.portage_const.INCREMENTALS)
1690 except Exception, e:
1691 raise SPMError("SPMError: %s: %s" % (Exception,e,))
1692 if use_cache:
1693 etpConst['spm']['cache']['portage']['config'][(config_root,root)] = mysettings
1694 return mysettings
1695
1698
1700 matched_atom = self.match_package(atom)
1701 if not matched_atom:
1702 return False
1703 use_file = self._get_package_use_file()
1704
1705 if not (os.path.isfile(use_file) and os.access(use_file,os.W_OK)):
1706 return False
1707 f = open(use_file,"r")
1708 content = [x.strip() for x in f.readlines()]
1709 f.close()
1710
1711 def handle_line(line, useflags):
1712
1713 data = line.split()
1714 if len(data) < 2:
1715 return False, line
1716
1717 myatom = data[0]
1718 if matched_atom != self.match_package(myatom):
1719 return False, line
1720
1721 flags = data[1:]
1722 base_flags = []
1723 added_flags = []
1724 for flag in flags:
1725 myflag = flag
1726 if myflag.startswith("+"):
1727 myflag = myflag[1:]
1728 elif myflag.startswith("-"):
1729 myflag = myflag[1:]
1730 if not myflag:
1731 continue
1732 base_flags.append(myflag)
1733
1734 for useflag in useflags:
1735 if mark+useflag in base_flags:
1736 continue
1737 added_flags.append(mark+useflag)
1738
1739 new_line = "%s %s" % (myatom, ' '.join(flags+added_flags))
1740 return True, new_line
1741
1742
1743 atom_found = False
1744 new_content = []
1745 for line in content:
1746
1747 changed, elaborated_line = handle_line(line, useflags)
1748 if changed: atom_found = True
1749 new_content.append(elaborated_line)
1750
1751 if not atom_found:
1752 myline = "%s %s" % (atom, ' '.join([mark+x for x in useflags]))
1753 new_content.append(myline)
1754
1755
1756 f = open(use_file+".tmp","w")
1757 for line in new_content:
1758 f.write(line+"\n")
1759 f.flush()
1760 f.close()
1761 os.rename(use_file+".tmp", use_file)
1762 return True
1763
1765 matched_atom = self.match_package(atom)
1766 if not matched_atom:
1767 return False
1768
1769 use_file = self._get_package_use_file()
1770 if not (os.path.isfile(use_file) and os.access(use_file,os.W_OK)):
1771 return False
1772
1773 with open(use_file, "r") as f:
1774 content = [x.strip() for x in f.readlines()]
1775
1776 new_content = []
1777 for line in content:
1778
1779 data = line.split()
1780 if len(data) < 2:
1781 new_content.append(line)
1782 continue
1783
1784 myatom = data[0]
1785 if matched_atom != self.match_package(myatom):
1786 new_content.append(line)
1787 continue
1788
1789 flags = data[1:]
1790 new_flags = []
1791 for flag in flags:
1792 myflag = flag
1793
1794 if myflag.startswith("+"):
1795 myflag = myflag[1:]
1796 elif myflag.startswith("-"):
1797 myflag = myflag[1:]
1798
1799 if myflag in useflags:
1800 continue
1801 elif not flag:
1802 continue
1803
1804 new_flags.append(flag)
1805
1806 if new_flags:
1807 new_line = "%s %s" % (myatom, ' '.join(new_flags))
1808 new_content.append(new_line)
1809
1810 with open(use_file+".tmp", "w") as f:
1811 for line in new_content:
1812 f.write(line+"\n")
1813 f.flush()
1814
1815 os.rename(use_file+".tmp", use_file)
1816 return True
1817
1819
1820 data = {
1821 'enabled': set(),
1822 'disabled': set(),
1823 }
1824
1825 matched_atom = self.match_package(atom)
1826 if not matched_atom:
1827 return data
1828
1829 use_file = self._get_package_use_file()
1830 if not (os.path.isfile(use_file) and os.access(use_file,os.W_OK)):
1831 return data
1832
1833 use_data = self.portage_util.grabdict(use_file)
1834 for myatom in use_data:
1835 mymatch = self.match_package(myatom)
1836 if mymatch != matched_atom:
1837 continue
1838 for flag in use_data[myatom]:
1839 if flag.startswith("-"):
1840 myflag = flag[1:]
1841 data['enabled'].discard(myflag)
1842 data['disabled'].add(myflag)
1843 else:
1844 myflag = flag
1845 if myflag.startswith("+"):
1846 myflag = myflag[1:]
1847 data['disabled'].discard(myflag)
1848 data['enabled'].add(myflag)
1849
1850 return data
1851
1853 return self.portage.settings['USE']
1854
1856 return self.portage.settings.useforce
1857
1859 return self.portage.settings.usemask
1860
1862 use = set()
1863 use_mask = self._get_useflags_mask()
1864 use_force = self._get_useflags_force()
1865 for myiuse in iuse_list:
1866 if myiuse[0] in ("+", "-",):
1867 myiuse = myiuse[1:]
1868 if ((myiuse in use_list) or (myiuse in use_force)) and \
1869 (myiuse not in use_mask):
1870 use.add(myiuse)
1871 return use
1872
1873 - def _calculate_dependencies(self, my_iuse, my_use, my_license, my_depend,
1874 my_rdepend, my_pdepend, my_provide, my_src_uri):
1875
1876 metadata = {
1877 'LICENSE': my_license,
1878 'DEPEND': my_depend,
1879 'PDEPEND': my_pdepend,
1880 'RDEPEND': my_rdepend,
1881 'PROVIDE': my_provide,
1882 'SRC_URI': my_src_uri,
1883 'USE_MASK': sorted(self._get_useflags_mask()),
1884 'USE_FORCE': sorted(self._get_useflags_force()),
1885 }
1886
1887 # generate USE flags metadata
1888 raw_use = my_use.split()
1889 enabled_use = sorted(self._resolve_enabled_useflags(
1890 my_iuse.split(), raw_use))
1891
1892 metadata['ENABLED_USE'] = enabled_use
1893 use = raw_use + [x for x in metadata['USE_FORCE'] if x not in raw_use]
1894 metadata['USE'] = sorted([unicode(x) for x in use if x not in \
1895 metadata['USE_MASK']])
1896
1897 for k in "LICENSE", "RDEPEND", "DEPEND", "PDEPEND", "PROVIDE", "SRC_URI":
1898 try:
1899 if k == "SRC_URI":
1900 deps = self._src_uri_paren_reduce(metadata[k])
1901 else:
1902 deps = self._paren_reduce(metadata[k])
1903 deps = self._use_reduce(deps, uselist = raw_use)
1904 deps = self.paren_normalize(deps)
1905 if k == "LICENSE":
1906 deps = self._paren_license_choose(deps)
1907 else:
1908 deps = self._paren_choose(deps)
1909 if k.endswith("DEPEND"):
1910 deps = self._usedeps_reduce(deps, enabled_use)
1911 deps = ' '.join(deps)
1912 except Exception, e:
1913 self.entropyTools.print_traceback()
1914 self.updateProgress(
1915 darkred("%s: %s: %s :: %s") % (
1916 _("Error calculating dependencies"),
1917 str(Exception),
1918 k,
1919 e,
1920 ),
1921 importance = 1,
1922 type = "error",
1923 header = red(" !!! ")
1924 )
1925 deps = ''
1926 continue
1927 metadata[k] = deps
1928 return metadata
1929
1931 src_uris = self._paren_reduce(src_uris)
1932 newlist = []
1933 skip_next = False
1934 for src_uri in src_uris:
1935 if skip_next:
1936 skip_next = False
1937 continue
1938 if src_uri == "->":
1939 skip_next = True
1940 continue
1941 newlist.append(src_uri)
1942 return newlist
1943
1945 newlist = []
1946
1947 def strip_use(xuse):
1948 myuse = xuse[:]
1949 if myuse[0] == "!":
1950 myuse = myuse[1:]
1951 if myuse[-1] in ("=","?",):
1952 myuse = myuse[:-1]
1953 return myuse
1954
1955 for dependency in dependencies:
1956 use_deps = self.entropyTools.dep_getusedeps(dependency)
1957 if use_deps:
1958 new_use_deps = []
1959 for use in use_deps:
1960 """
1961 explicitly support only specific types
1962 """
1963 if (use[0] == "!") and (use[-1] not in ("=","?",)):
1964 # this does not exist atm
1965 continue
1966 elif use[-1] == "=":
1967 if use[0] == "!":
1968 # foo[!bar=] means bar? ( foo[-bar] ) !bar? ( foo[bar] )
1969 s_use = strip_use(use)
1970 if s_use in enabled_useflags:
1971 new_use_deps.append("-%s" % (s_use,))
1972 else:
1973 new_use_deps.append(s_use)
1974 continue
1975 else:
1976 # foo[bar=] means bar? ( foo[bar] ) !bar? ( foo[-bar] )
1977 s_use = strip_use(use)
1978 if s_use in enabled_useflags:
1979 new_use_deps.append(s_use)
1980 else:
1981 new_use_deps.append("-%s" % (s_use,))
1982 continue
1983 elif use[-1] == "?":
1984 if use[0] == "!":
1985 # foo[!bar?] means bar? ( foo ) !bar? ( foo[-bar] )
1986 s_use = strip_use(use)
1987 if s_use not in enabled_useflags:
1988 new_use_deps.append("-%s" % (s_use,))
1989 continue
1990 else:
1991 # foo[bar?] means bar? ( foo[bar] ) !bar? ( foo )
1992 s_use = strip_use(use)
1993 if s_use in enabled_useflags:
1994 new_use_deps.append(s_use)
1995 continue
1996 new_use_deps.append(use)
1997
1998 if new_use_deps:
1999 dependency = "%s[%s]" % (
2000 self.entropyTools.remove_usedeps(dependency),
2001 ','.join(new_use_deps),
2002 )
2003 else:
2004 dependency = self.entropyTools.remove_usedeps(dependency)
2005
2006 newlist.append(dependency)
2007 return newlist
2008
2010 """
2011
2012 # deps.py -- Portage dependency resolution functions
2013 # Copyright 2003-2004 Gentoo Foundation
2014 # Distributed under the terms of the GNU General Public License v2
2015 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $
2016
2017 Take a string and convert all paren enclosed entities into sublists, optionally
2018 futher splitting the list elements by spaces.
2019
2020 Example usage:
2021 >>> paren_reduce('foobar foo ( bar baz )',1)
2022 ['foobar', 'foo', ['bar', 'baz']]
2023 >>> paren_reduce('foobar foo ( bar baz )',0)
2024 ['foobar foo ', [' bar baz ']]
2025
2026 @param mystr: The string to reduce
2027 @type mystr: String
2028 @rtype: Array
2029 @return: The reduced string in an array
2030 """
2031 mylist = []
2032 while mystr:
2033 left_paren = mystr.find("(")
2034 has_left_paren = left_paren != -1
2035 right_paren = mystr.find(")")
2036 has_right_paren = right_paren != -1
2037 if not has_left_paren and not has_right_paren:
2038 freesec = mystr
2039 subsec = None
2040 tail = ""
2041 elif mystr[0] == ")":
2042 return [mylist,mystr[1:]]
2043 elif has_left_paren and not has_right_paren:
2044 raise InvalidDependString(
2045 "InvalidDependString: %s: '%s'" % (_("missing right parenthesis"),mystr,))
2046 elif has_left_paren and left_paren < right_paren:
2047 freesec,subsec = mystr.split("(",1)
2048 subsec,tail = self._paren_reduce(subsec)
2049 else:
2050 subsec,tail = mystr.split(")",1)
2051 subsec = self._strip_empty(subsec.split(" "))
2052 return [mylist+subsec,tail]
2053 mystr = tail
2054 if freesec:
2055 mylist = mylist + self._strip_empty(freesec.split(" "))
2056 if subsec is not None:
2057 mylist = mylist + [subsec]
2058 return mylist
2059
2061 """
2062
2063 # deps.py -- Portage dependency resolution functions
2064 # Copyright 2003-2004 Gentoo Foundation
2065 # Distributed under the terms of the GNU General Public License v2
2066 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $
2067
2068 Strip all empty elements from an array
2069
2070 @param myarr: The list of elements
2071 @type myarr: List
2072 @rtype: Array
2073 @return: The array with empty elements removed
2074 """
2075 for x in range(len(myarr)-1, -1, -1):
2076 if not myarr[x]:
2077 del myarr[x]
2078 return myarr
2079
2080 - def _use_reduce(self, deparray, uselist = None, masklist = None,
2081 matchall = 0, excludeall = None):
2082 """
2083
2084 # deps.py -- Portage dependency resolution functions
2085 # Copyright 2003-2004 Gentoo Foundation
2086 # Distributed under the terms of the GNU General Public License v2
2087 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $
2088
2089 Takes a paren_reduce'd array and reduces the use? conditionals out
2090 leaving an array with subarrays
2091
2092 @param deparray: paren_reduce'd list of deps
2093 @type deparray: List
2094 @param uselist: List of use flags
2095 @type uselist: List
2096 @param masklist: List of masked flags
2097 @type masklist: List
2098 @param matchall: Resolve all conditional deps unconditionally. Used by repoman
2099 @type matchall: Integer
2100 @rtype: List
2101 @return: The use reduced depend array
2102 """
2103
2104 if uselist is None:
2105 uselist = []
2106 if masklist is None:
2107 masklist = []
2108 if excludeall is None:
2109 excludeall = []
2110
2111 # Quick validity checks
2112 for x in range(len(deparray)):
2113 if deparray[x] in ["||","&&"]:
2114 if len(deparray) - 1 == x or not isinstance(deparray[x+1], list):
2115 mytxt = _("missing atom list in")
2116 raise InvalidDependString(deparray[x]+" "+mytxt+" \""+str(deparray)+"\"")
2117 if deparray and deparray[-1] and deparray[-1][-1] == "?":
2118 mytxt = _("Conditional without target in")
2119 raise InvalidDependString("InvalidDependString: "+mytxt+" \""+str(deparray)+"\"")
2120
2121 # This is just for use by emerge so that it can enable a backward compatibility
2122 # mode in order to gracefully deal with installed packages that have invalid
2123 # atoms or dep syntax. For backward compatibility with api consumers, strict
2124 # behavior will be explicitly enabled as necessary.
2125 _dep_check_strict = False
2126
2127 mydeparray = deparray[:]
2128 rlist = []
2129 while mydeparray:
2130 head = mydeparray.pop(0)
2131
2132 if isinstance(head,list):
2133 additions = self._use_reduce(head, uselist, masklist, matchall, excludeall)
2134 if additions:
2135 rlist.append(additions)
2136 elif rlist and rlist[-1] == "||":
2137 #XXX: Currently some DEPEND strings have || lists without default atoms.
2138 # raise portage_exception.InvalidDependString("No default atom(s) in \""+paren_enclose(deparray)+"\"")
2139 rlist.append([])
2140 else:
2141 if head[-1] == "?": # Use reduce next group on fail.
2142 # Pull any other use conditions and the following atom or list into a separate array
2143 newdeparray = [head]
2144 while isinstance(newdeparray[-1], basestring) and newdeparray[-1][-1] == "?":
2145 if mydeparray:
2146 newdeparray.append(mydeparray.pop(0))
2147 else:
2148 raise ValueError, _("Conditional with no target")
2149
2150 # Deprecation checks
2151 warned = 0
2152 if len(newdeparray[-1]) == 0:
2153 mytxt = "%s. (%s)" % (_("Empty target in string"),_("Deprecated"),)
2154 self.updateProgress(
2155 darkred("PortagePlugin._use_reduce(): %s" % (mytxt,)),
2156 importance = 0,
2157 type = "error",
2158 header = bold(" !!! ")
2159 )
2160 warned = 1
2161 if len(newdeparray) != 2:
2162 mytxt = "%s. (%s)" % (_("Nested use flags without parenthesis"),_("Deprecated"),)
2163 self.updateProgress(
2164 darkred("PortagePlugin._use_reduce(): %s" % (mytxt,)),
2165 importance = 0,
2166 type = "error",
2167 header = bold(" !!! ")
2168 )
2169 warned = 1
2170 if warned:
2171 self.updateProgress(
2172 darkred("PortagePlugin._use_reduce(): "+" ".join(map(str,[head]+newdeparray))),
2173 importance = 0,
2174 type = "error",
2175 header = bold(" !!! ")
2176 )
2177
2178 # Check that each flag matches
2179 ismatch = True
2180 missing_flag = False
2181 for head in newdeparray[:-1]:
2182 head = head[:-1]
2183 if not head:
2184 missing_flag = True
2185 break
2186 if head.startswith("!"):
2187 head_key = head[1:]
2188 if not head_key:
2189 missing_flag = True
2190 break
2191 if not matchall and head_key in uselist or \
2192 head_key in excludeall:
2193 ismatch = False
2194 break
2195 elif head not in masklist:
2196 if not matchall and head not in uselist:
2197 ismatch = False
2198 break
2199 else:
2200 ismatch = False
2201 if missing_flag:
2202 mytxt = _("Conditional without flag")
2203 raise InvalidDependString(
2204 "InvalidDependString: "+mytxt+": \"" + \
2205 str([head+"?", newdeparray[-1]])+"\"")
2206
2207 # If they all match, process the target
2208 if ismatch:
2209 target = newdeparray[-1]
2210 if isinstance(target, list):
2211 additions = self._use_reduce(target, uselist, masklist, matchall, excludeall)
2212 if additions:
2213 rlist.append(additions)
2214 elif not _dep_check_strict:
2215 # The old deprecated behavior.
2216 rlist.append(target)
2217 else:
2218 mytxt = _("Conditional without parenthesis")
2219 raise InvalidDependString(
2220 "InvalidDependString: "+mytxt+": '%s?'" % head)
2221
2222 else:
2223 rlist += [head]
2224 return rlist
2225
2227 newlist = []
2228 do_skip = False
2229 for idx in range(len(dep_list)):
2230
2231 if do_skip:
2232 do_skip = False
2233 continue
2234
2235 item = dep_list[idx]
2236 if item == "||": # or
2237 next_item = dep_list[idx+1]
2238 if not next_item: # || ( asd? ( atom ) dsa? ( atom ) ) => [] if use asd and dsa are disabled
2239 do_skip = True
2240 continue
2241 item = self._dep_or_select(next_item) # must be a list
2242 if not item:
2243 # no matches, transform to string and append, so reagent will fail
2244 newlist.append(str(next_item))
2245 else:
2246 newlist += item
2247 do_skip = True
2248 elif isinstance(item, list): # and
2249 item = self._dep_and_select(item)
2250 newlist += item
2251 else:
2252 newlist.append(item)
2253
2254 return newlist
2255
2257 do_skip = False
2258 newlist = []
2259 for idx in range(len(and_list)):
2260
2261 if do_skip:
2262 do_skip = False
2263 continue
2264
2265 x = and_list[idx]
2266 if x == "||":
2267 x = self._dep_or_select(and_list[idx+1])
2268 do_skip = True
2269 if not x:
2270 x = str(and_list[idx+1])
2271 else:
2272 newlist += x
2273 elif isinstance(x, list):
2274 x = self._dep_and_select(x)
2275 newlist += x
2276 else:
2277 newlist.append(x)
2278
2279 # now verify if all are satisfied
2280 for x in newlist:
2281 match = self.match_installed_package(x)
2282 if not match:
2283 return []
2284
2285 return newlist
2286
2288 do_skip = False
2289 for idx in range(len(or_list)):
2290 if do_skip:
2291 do_skip = False
2292 continue
2293 x = or_list[idx]
2294 if x == "||": # or
2295 x = self._dep_or_select(or_list[idx+1])
2296 do_skip = True
2297 elif isinstance(x, list): # and
2298 x = self._dep_and_select(x)
2299 if not x:
2300 continue
2301 # found
2302 return x
2303 else:
2304 x = [x]
2305
2306 for y in x:
2307 match = self.match_installed_package(y)
2308 if match:
2309 return [y]
2310
2311 return []
2312
2314
2315 newlist = set()
2316 for item in dep_list:
2317
2318 if isinstance(item, list):
2319 # match the first
2320 data = set(self._paren_license_choose(item))
2321 newlist.update(data)
2322 else:
2323 if item not in ["||"]:
2324 newlist.add(item)
2325
2326 return list(newlist)
2327
2329 if root is None:
2330 root = etpConst['systemroot'] + os.path.sep
2331 return os.path.join(root, self.portage_const.VDB_PATH)
2332
2334
2335 # from portage.const import USER_CONFIG_PATH, GLOBAL_CONFIG_PATH
2336 setconfigpaths = [os.path.join(self.portage_const.GLOBAL_CONFIG_PATH, etpConst['setsconffilename'])]
2337 setconfigpaths.append(os.path.join(settings["PORTDIR"], etpConst['setsconffilename']))
2338 setconfigpaths += [os.path.join(x, etpConst['setsconffilename']) for x in settings["PORTDIR_OVERLAY"].split()]
2339 setconfigpaths.append(os.path.join(settings["PORTAGE_CONFIGROOT"],
2340 self.portage_const.USER_CONFIG_PATH.lstrip(os.path.sep), etpConst['setsconffilename']))
2341 return self.portage_sets.SetConfig(setconfigpaths, settings, trees)
2342
2344 # old portage
2345 if self.portage_sets == None:
2346 return
2347 myroot = etpConst['systemroot'] + os.path.sep
2348 return self._load_sets_config(
2349 self.portage.settings,
2350 self.portage.db[myroot]
2351 )
2352
2354 data = {
2355 'pf': {
2356 'path': etpConst['spm']['xpak_entries']['pf'],
2357 'critical': True,
2358 },
2359 'chost': {
2360 'path': etpConst['spm']['xpak_entries']['chost'],
2361 'critical': True,
2362 },
2363 'description': {
2364 'path': etpConst['spm']['xpak_entries']['description'],
2365 'critical': False,
2366 },
2367 'homepage': {
2368 'path': etpConst['spm']['xpak_entries']['homepage'],
2369 'critical': False,
2370 },
2371 'slot': {
2372 'path': etpConst['spm']['xpak_entries']['slot'],
2373 'critical': False,
2374 },
2375 'cflags': {
2376 'path': etpConst['spm']['xpak_entries']['cflags'],
2377 'critical': False,
2378 },
2379 'cxxflags': {
2380 'path': etpConst['spm']['xpak_entries']['cxxflags'],
2381 'critical': False,
2382 },
2383 'category': {
2384 'path': etpConst['spm']['xpak_entries']['category'],
2385 'critical': True,
2386 },
2387 'rdepend': {
2388 'path': etpConst['spm']['xpak_entries']['rdepend'],
2389 'critical': False,
2390 },
2391 'pdepend': {
2392 'path': etpConst['spm']['xpak_entries']['pdepend'],
2393 'critical': False,
2394 },
2395 'depend': {
2396 'path': etpConst['spm']['xpak_entries']['depend'],
2397 'critical': False,
2398 },
2399 'use': {
2400 'path': etpConst['spm']['xpak_entries']['use'],
2401 'critical': False,
2402 },
2403 'iuse': {
2404 'path': etpConst['spm']['xpak_entries']['iuse'],
2405 'critical': False,
2406 },
2407 'license': {
2408 'path': etpConst['spm']['xpak_entries']['license'],
2409 'critical': False,
2410 },
2411 'provide': {
2412 'path': etpConst['spm']['xpak_entries']['provide'],
2413 'critical': False,
2414 },
2415 'sources': {
2416 'path': etpConst['spm']['xpak_entries']['src_uri'],
2417 'critical': False,
2418 },
2419 'eclasses': {
2420 'path': etpConst['spm']['xpak_entries']['inherited'],
2421 'critical': False,
2422 },
2423 'counter': {
2424 'path': etpConst['spm']['xpak_entries']['counter'],
2425 'critical': False,
2426 },
2427 'keywords': {
2428 'path': etpConst['spm']['xpak_entries']['keywords'],
2429 'critical': False,
2430 },
2431 'spm_phases': {
2432 'path': etpConst['spm']['xpak_entries']['defined_phases'],
2433 'critical': False,
2434 },
2435 }
2436 return data
2437
2439
2440 pkg_content = {}
2441
2442 if os.path.isfile(content_file):
2443
2444 f = open(content_file,"r")
2445 content = [x.decode('raw_unicode_escape') for x in f.readlines()]
2446 f.close()
2447 outcontent = set()
2448 for line in content:
2449 line = line.strip().split()
2450 try:
2451 datatype = line[0]
2452 datafile = line[1:]
2453 if datatype == 'obj':
2454 datafile = datafile[:-2]
2455 datafile = ' '.join(datafile)
2456 elif datatype == 'dir':
2457 datafile = ' '.join(datafile)
2458 elif datatype == 'sym':
2459 datafile = datafile[:-3]
2460 datafile = ' '.join(datafile)
2461 else:
2462 myexc = "InvalidData: %s %s. %s." % (
2463 datafile,
2464 _("not supported"),
2465 _("Probably Portage API has changed"),
2466 )
2467 raise InvalidData(myexc)
2468 outcontent.add((datafile,datatype))
2469 except:
2470 pass
2471
2472 outcontent = sorted(outcontent)
2473 for datafile, datatype in outcontent:
2474 pkg_content[datafile] = datatype
2475
2476 else:
2477
2478 # CONTENTS is not generated when a package is emerged with portage and the option -B
2479 # we have to unpack the tbz2 and generate content dict
2480 mytempdir = etpConst['packagestmpdir']+"/"+os.path.basename(package_path)+".inject"
2481 if os.path.isdir(mytempdir):
2482 shutil.rmtree(mytempdir)
2483 if not os.path.isdir(mytempdir):
2484 os.makedirs(mytempdir)
2485
2486 self.entropyTools.uncompress_tar_bz2(package_path, extractPath = mytempdir, catchEmpty = True)
2487 tmpdir_len = len(mytempdir)
2488 for currentdir, subdirs, files in os.walk(mytempdir):
2489 pkg_content[currentdir[tmpdir_len:]] = u"dir"
2490 for item in files:
2491 item = currentdir+"/"+item
2492 if os.path.islink(item):
2493 pkg_content[item[tmpdir_len:]] = u"sym"
2494 else:
2495 pkg_content[item[tmpdir_len:]] = u"obj"
2496
2497 # now remove
2498 shutil.rmtree(mytempdir,True)
2499 try:
2500 os.rmdir(mytempdir)
2501 except (OSError,):
2502 pass
2503
2504 return pkg_content
2505
2507
2508 pkg_needed = set()
2509 lines = []
2510
2511 try:
2512 f = open(needed_file,"r")
2513 lines = [x.decode('raw_unicode_escape').strip() for x in f.readlines() if x.strip()]
2514 f.close()
2515 except IOError:
2516 return lines
2517
2518 for line in lines:
2519 needed = line.split()
2520 if len(needed) == 2:
2521 ownlib = needed[0]
2522 ownelf = -1
2523 if os.access(ownlib,os.R_OK):
2524 ownelf = self.entropyTools.read_elf_class(ownlib)
2525 for lib in needed[1].split(","):
2526 #if lib.find(".so") != -1:
2527 pkg_needed.add((lib,ownelf))
2528
2529 return sorted(pkg_needed)
2530
2532
2533 data = {}
2534 ldpaths = self.entropyTools.collect_linker_paths()
2535
2536 for needed_lib, elf_class in needed_libs:
2537 for ldpath in ldpaths:
2538 my_lib = os.path.join(ldpath, needed_lib)
2539 if not os.access(my_lib, os.R_OK):
2540 continue
2541 myclass = self.entropyTools.read_elf_class(my_lib)
2542 if myclass != elf_class:
2543 continue
2544 obj = data.setdefault(needed_lib, set())
2545 obj.add((my_lib, myclass,))
2546
2547 return data
2548
2550
2551 pkg_messages = []
2552 if not os.path.isdir(log_dir):
2553 return pkg_messages
2554
2555 elogfiles = os.listdir(log_dir)
2556 myelogfile = "%s:%s-%s" % (category, name, version,)
2557 foundfiles = [x for x in elogfiles if x.startswith(myelogfile)]
2558 if foundfiles:
2559 elogfile = foundfiles[0]
2560 if len(foundfiles) > 1:
2561 # get the latest
2562 mtimes = []
2563 for item in foundfiles: mtimes.append((self.entropyTools.get_file_unix_mtime(os.path.join(log_dir,item)),item))
2564 mtimes = sorted(mtimes)
2565 elogfile = mtimes[-1][1]
2566 messages = self.entropyTools.extract_elog(os.path.join(log_dir,elogfile))
2567 for message in messages:
2568 message = message.replace("emerge","install")
2569 pkg_messages.append(message.decode('raw_unicode_escape'))
2570
2571 return pkg_messages
2572
2574
2575 pkg_licensedata = {}
2576 if licenses_dir and os.path.isdir(licenses_dir):
2577 licdata = [x.strip() for x in license_string.split() if x.strip() and self.entropyTools.is_valid_string(x.strip())]
2578 for mylicense in licdata:
2579 licfile = os.path.join(licenses_dir,mylicense)
2580 if os.access(licfile,os.R_OK):
2581 if self.entropyTools.istextfile(licfile):
2582 f = open(licfile)
2583 content = ''
2584 line = f.readline()
2585 while line:
2586 content += line
2587 line = f.readline()
2588 try:
2589 try:
2590 pkg_licensedata[mylicense] = content.decode('raw_unicode_escape')
2591 except UnicodeDecodeError:
2592 pkg_licensedata[mylicense] = unicode(content,'utf-8')
2593 except (UnicodeDecodeError, UnicodeEncodeError,):
2594 continue # sorry!
2595 f.close()
2596
2597 return pkg_licensedata
2598
2600
2601 # =mirror://openoffice|link1|link2|link3
2602 pkg_links = []
2603 for i in sources_list:
2604 if i.startswith("mirror://"):
2605 # parse what mirror I need
2606 mirrorURI = i.split("/")[2]
2607 mirrorlist = set(self.get_download_mirrors(mirrorURI))
2608 pkg_links.append([mirrorURI,mirrorlist])
2609 # mirrorURI = openoffice and mirrorlist = [link1, link2, link3]
2610
2611 return pkg_links
2612
2614 search_tag = etpConst['spm']['ebuild_pkg_tag_var']
2615 ebuild_tag = ''
2616 f = open(ebuild,"r")
2617 tags = [x.strip().decode('raw_unicode_escape') for x in f.readlines() if x.strip() and x.strip().startswith(search_tag)]
2618 f.close()
2619 if not tags: return ebuild_tag
2620 tag = tags[-1]
2621 tag = tag.split("=")[-1].strip('"').strip("'").strip()
2622 return tag
2623
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Thu Sep 3 14:56:15 2009 | http://epydoc.sourceforge.net |