| 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
26 import entropy.tools
29 """
30 Entropy Package categories group representation
31 """
33 dict.__init__(self)
34
35 data = {
36 'office': {
37 'name': _("Office"),
38 'description': _("Applications used in office environments"),
39 'categories': [u'app-office', u'app-pda', u'app-mobilephone',
40 u'app-cdr', u'app-antivirus', u'app-laptop', u'mail-',
41 ],
42 },
43 'development': {
44 'name': _("Development"),
45 'description': _("Applications or system libraries"),
46 'categories': [u'dev-', u'sys-devel'],
47 },
48 'system': {
49 'name': _("System"),
50 'description': _("System applications or libraries"),
51 'categories': [u'sys-'],
52 },
53 'games': {
54 'name': _("Games"),
55 'description': _("Games, enjoy your spare time"),
56 'categories': [u'games-'],
57 },
58 'gnome': {
59 'name': _("GNOME Desktop"),
60 'description': \
61 _("Applications and libraries for the GNOME Desktop"),
62 'categories': [u'gnome-'],
63 },
64 'kde': {
65 'name': _("KDE Desktop"),
66 'description': \
67 _("Applications and libraries for the KDE Desktop"),
68 'categories': [u'kde-'],
69 },
70 'xfce': {
71 'name': _("XFCE Desktop"),
72 'description': \
73 _("Applications and libraries for the XFCE Desktop"),
74 'categories': [u'xfce-'],
75 },
76 'lxde': {
77 'name': _("LXDE Desktop"),
78 'description': \
79 _("Applications and libraries for the LXDE Desktop"),
80 'categories': [u'lxde-'],
81 },
82 'multimedia': {
83 'name': _("Multimedia"),
84 'description': \
85 _("Applications and libraries for Multimedia"),
86 'categories': [u'media-'],
87 },
88 'networking': {
89 'name': _("Networking"),
90 'description': \
91 _("Applications and libraries for Networking"),
92 'categories': [u'net-', u'www-'],
93 },
94 'science': {
95 'name': _("Science"),
96 'description': \
97 _("Scientific applications and libraries"),
98 'categories': [u'sci-'],
99 },
100 'x11': {
101 'name': _("X11"),
102 'description': \
103 _("Applications and libraries for X11"),
104 'categories': [u'x11-'],
105 },
106 }
107 self.update(data)
108
110
111 builtin_pkg_sets = [
112 "system","world","installed","module-rebuild",
113 "security","preserved-rebuild","live-rebuild",
114 "downgrade","unavailable"
115 ]
116
117 package_phases_map = {
118 'setup': 'setup',
119 'preinstall': 'preinst',
120 'postinstall': 'postinst',
121 'preremove': 'prerm',
122 'postremove': 'postrm',
123 'configure': 'config',
124 }
125
126 PLUGIN_API_VERSION = 0
127
128 SUPPORTED_MATCH_TYPES = [
129 "bestmatch-visible", "cp-list", "list-visible", "match-all",
130 "match-visible", "minimum-all", "minimum-visible"
131 ]
132
134 """Take a dependency structure as returned by paren_reduce or use_reduce
135 and generate an equivalent structure that has no redundant lists."""
139
141 if not src:
142 return dest
143 i = iter(src)
144 for x in i:
145 if isinstance(x, basestring):
146 if x == '||':
147 x = self._zap_parens(i.next(), [], disjunction=True)
148 if len(x) == 1:
149 dest.append(x[0])
150 else:
151 dest.append("||")
152 dest.append(x)
153 elif x.endswith("?"):
154 dest.append(x)
155 dest.append(self._zap_parens(i.next(), []))
156 else:
157 dest.append(x)
158 else:
159 if disjunction:
160 x = self._zap_parens(x, [])
161 if len(x) == 1:
162 dest.append(x[0])
163 else:
164 dest.append(x)
165 else:
166 self._zap_parens(x, dest)
167 return dest
168
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'] = entropy.tools.md5sum(package_file)
593 data['signatures'] = {
594 'sha1': entropy.tools.sha1(package_file),
595 'sha256': entropy.tools.sha256(package_file),
596 'sha512': entropy.tools.sha512(package_file),
597 }
598 data['datecreation'] = str(entropy.tools.get_file_unix_mtime(
599 package_file))
600 data['size'] = str(entropy.tools.get_file_size(package_file))
601
602 tmp_dir = tempfile.mkdtemp()
603 entropy.tools.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 = entropy.tools.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'] = entropy.tools.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'] += entropy.tools.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 = [entropy.tools.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 entropy.tools.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(entropy.tools.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 = entropy.tools.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(entropy.tools.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 == entropy.tools.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 entropy.tools.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 = entropy.tools.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 = entropy.tools.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 entropy.tools.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
1618 @staticmethod
1620 """
1621 Reimplemented from SpmPlugin class.
1622 """
1623 package_metadata['xpakpath'] = etpConst['entropyunpackdir'] + \
1624 os.path.sep + package_metadata['download'] + os.path.sep + \
1625 etpConst['entropyxpakrelativepath']
1626
1627 if not package_metadata['merge_from']:
1628
1629 package_metadata['xpakstatus'] = None
1630 package_metadata['xpakdir'] = package_metadata['xpakpath'] + \
1631 os.path.sep + etpConst['entropyxpakdatarelativepath']
1632
1633 else:
1634
1635 package_metadata['xpakstatus'] = True
1636
1637 try:
1638 try:
1639 import portage.const as portage_const
1640 except ImportError:
1641 import portage_const
1642 portdbdir = portage_const.VDB_PATH
1643 except ImportError:
1644 portdbdir = 'var/db/pkg'
1645
1646 portdbdir = os.path.join(package_metadata['merge_from'], portdbdir)
1647 portdbdir = os.path.join(portdbdir, package_metadata['category'])
1648 portdbdir = os.path.join(portdbdir, package_metadata['name'] + \
1649 "-" + package_metadata['version'])
1650
1651 package_metadata['xpakdir'] = portdbdir
1652
1653 package_metadata['triggers']['install']['xpakdir'] = \
1654 package_metadata['xpakdir']
1655
1656 return 0
1657
1658 @staticmethod
1660 """
1661 Reimplemented from SpmPlugin class.
1662 """
1663 # unpack xpak ?
1664 if os.path.isdir(package_metadata['xpakpath']):
1665 shutil.rmtree(package_metadata['xpakpath'], True)
1666
1667 # create data dir where we'll unpack the xpak
1668 xpak_dir = package_metadata['xpakpath'] + os.path.sep + \
1669 etpConst['entropyxpakdatarelativepath']
1670
1671 os.makedirs(xpak_dir, 0755)
1672
1673 xpak_path = package_metadata['xpakpath'] + os.path.sep + \
1674 etpConst['entropyxpakfilename']
1675
1676 if not package_metadata['merge_from']:
1677
1678 if package_metadata['smartpackage']:
1679
1680 # we need to get the .xpak from database
1681 xdbconn = entropy_client.open_repository(
1682 package_metadata['repository'])
1683 xpakdata = xdbconn.retrieveXpakMetadata(
1684 package_metadata['idpackage'])
1685 if xpakdata:
1686 # save into a file
1687 with open(xpak_path, "wb") as xpak_f:
1688 xpak_f.write(xpakdata)
1689 xpak_f.flush()
1690 package_metadata['xpakstatus'] = \
1691 entropy.tools.unpack_xpak(
1692 xpak_path,
1693 xpak_dir
1694 )
1695 else:
1696 package_metadata['xpakstatus'] = None
1697 del xpakdata
1698
1699 else:
1700 package_metadata['xpakstatus'] = entropy.tools.extract_xpak(
1701 package_metadata['pkgpath'],
1702 xpak_dir
1703 )
1704
1705 else: # merge_from
1706
1707 tolink_dir = xpak_dir
1708 if os.path.isdir(tolink_dir):
1709 shutil.rmtree(tolink_dir, True)
1710 # now link
1711 os.symlink(package_metadata['xpakdir'], tolink_dir)
1712
1713 # create fake portage ${D} linking it to imagedir
1714 portage_cpv = package_metadata['category'] + "/" + \
1715 package_metadata['name'] + "-" + package_metadata['version']
1716
1717 portage_db_fakedir = os.path.join(
1718 package_metadata['unpackdir'],
1719 "portage/" + portage_cpv
1720 )
1721
1722 os.makedirs(portage_db_fakedir, 0755)
1723 # now link it to package_metadata['imagedir']
1724 os.symlink(package_metadata['imagedir'],
1725 os.path.join(portage_db_fakedir, "image"))
1726
1727 return 0
1728
1730
1731 if root is None:
1732 root = etpConst['systemroot'] + os.path.sep
1733
1734 if not etpConst['spm']['cache'].has_key('portage'):
1735 etpConst['spm']['cache']['portage'] = {}
1736 if not etpConst['spm']['cache']['portage'].has_key('vartree'):
1737 etpConst['spm']['cache']['portage']['vartree'] = {}
1738
1739 cached = etpConst['spm']['cache']['portage']['vartree'].get(root)
1740 if cached != None:
1741 return cached
1742
1743 try:
1744 mytree = self.portage.vartree(root=root)
1745 except Exception, e:
1746 raise SPMError("SPMError: %s: %s" % (Exception,e,))
1747 etpConst['spm']['cache']['portage']['vartree'][root] = mytree
1748 return mytree
1749
1751
1752 if not etpConst['spm']['cache'].has_key('portage'):
1753 etpConst['spm']['cache']['portage'] = {}
1754 if not etpConst['spm']['cache']['portage'].has_key('portagetree'):
1755 etpConst['spm']['cache']['portage']['portagetree'] = {}
1756
1757 cached = etpConst['spm']['cache']['portage']['portagetree'].get(root)
1758 if cached != None:
1759 return cached
1760
1761 try:
1762 mytree = self.portage.portagetree(root=root)
1763 except Exception, e:
1764 raise SPMError("SPMError: %s: %s" % (Exception,e,))
1765 etpConst['spm']['cache']['portage']['portagetree'][root] = mytree
1766 return mytree
1767
1769
1770 if not etpConst['spm']['cache'].has_key('portage'):
1771 etpConst['spm']['cache']['portage'] = {}
1772 if not etpConst['spm']['cache']['portage'].has_key('binarytree'):
1773 etpConst['spm']['cache']['portage']['binarytree'] = {}
1774
1775 cached = etpConst['spm']['cache']['portage']['binarytree'].get(root)
1776 if cached != None:
1777 return cached
1778
1779 pkgdir = root+self.portage.settings['PKGDIR']
1780 try:
1781 mytree = self.portage.binarytree(root,pkgdir)
1782 except Exception, e:
1783 raise SPMError("SPMError: %s: %s" % (Exception,e,))
1784 etpConst['spm']['cache']['portage']['binarytree'][root] = mytree
1785 return mytree
1786
1788
1789 if use_cache:
1790 if not etpConst['spm']['cache'].has_key('portage'):
1791 etpConst['spm']['cache']['portage'] = {}
1792 if not etpConst['spm']['cache']['portage'].has_key('config'):
1793 etpConst['spm']['cache']['portage']['config'] = {}
1794
1795 cached = etpConst['spm']['cache']['portage']['config'].get((config_root,root))
1796 if cached != None:
1797 return cached
1798
1799 try:
1800 mysettings = self.portage.config(config_root = config_root, target_root = root, config_incrementals = self.portage_const.INCREMENTALS)
1801 except Exception, e:
1802 raise SPMError("SPMError: %s: %s" % (Exception,e,))
1803 if use_cache:
1804 etpConst['spm']['cache']['portage']['config'][(config_root,root)] = mysettings
1805 return mysettings
1806
1809
1811 matched_atom = self.match_package(atom)
1812 if not matched_atom:
1813 return False
1814 use_file = self._get_package_use_file()
1815
1816 if not (os.path.isfile(use_file) and os.access(use_file,os.W_OK)):
1817 return False
1818 f = open(use_file,"r")
1819 content = [x.strip() for x in f.readlines()]
1820 f.close()
1821
1822 def handle_line(line, useflags):
1823
1824 data = line.split()
1825 if len(data) < 2:
1826 return False, line
1827
1828 myatom = data[0]
1829 if matched_atom != self.match_package(myatom):
1830 return False, line
1831
1832 flags = data[1:]
1833 base_flags = []
1834 added_flags = []
1835 for flag in flags:
1836 myflag = flag
1837 if myflag.startswith("+"):
1838 myflag = myflag[1:]
1839 elif myflag.startswith("-"):
1840 myflag = myflag[1:]
1841 if not myflag:
1842 continue
1843 base_flags.append(myflag)
1844
1845 for useflag in useflags:
1846 if mark+useflag in base_flags:
1847 continue
1848 added_flags.append(mark+useflag)
1849
1850 new_line = "%s %s" % (myatom, ' '.join(flags+added_flags))
1851 return True, new_line
1852
1853
1854 atom_found = False
1855 new_content = []
1856 for line in content:
1857
1858 changed, elaborated_line = handle_line(line, useflags)
1859 if changed: atom_found = True
1860 new_content.append(elaborated_line)
1861
1862 if not atom_found:
1863 myline = "%s %s" % (atom, ' '.join([mark+x for x in useflags]))
1864 new_content.append(myline)
1865
1866
1867 f = open(use_file+".tmp","w")
1868 for line in new_content:
1869 f.write(line+"\n")
1870 f.flush()
1871 f.close()
1872 os.rename(use_file+".tmp", use_file)
1873 return True
1874
1876 matched_atom = self.match_package(atom)
1877 if not matched_atom:
1878 return False
1879
1880 use_file = self._get_package_use_file()
1881 if not (os.path.isfile(use_file) and os.access(use_file,os.W_OK)):
1882 return False
1883
1884 with open(use_file, "r") as f:
1885 content = [x.strip() for x in f.readlines()]
1886
1887 new_content = []
1888 for line in content:
1889
1890 data = line.split()
1891 if len(data) < 2:
1892 new_content.append(line)
1893 continue
1894
1895 myatom = data[0]
1896 if matched_atom != self.match_package(myatom):
1897 new_content.append(line)
1898 continue
1899
1900 flags = data[1:]
1901 new_flags = []
1902 for flag in flags:
1903 myflag = flag
1904
1905 if myflag.startswith("+"):
1906 myflag = myflag[1:]
1907 elif myflag.startswith("-"):
1908 myflag = myflag[1:]
1909
1910 if myflag in useflags:
1911 continue
1912 elif not flag:
1913 continue
1914
1915 new_flags.append(flag)
1916
1917 if new_flags:
1918 new_line = "%s %s" % (myatom, ' '.join(new_flags))
1919 new_content.append(new_line)
1920
1921 with open(use_file+".tmp", "w") as f:
1922 for line in new_content:
1923 f.write(line+"\n")
1924 f.flush()
1925
1926 os.rename(use_file+".tmp", use_file)
1927 return True
1928
1930
1931 data = {
1932 'enabled': set(),
1933 'disabled': set(),
1934 }
1935
1936 matched_atom = self.match_package(atom)
1937 if not matched_atom:
1938 return data
1939
1940 use_file = self._get_package_use_file()
1941 if not (os.path.isfile(use_file) and os.access(use_file,os.W_OK)):
1942 return data
1943
1944 use_data = self.portage_util.grabdict(use_file)
1945 for myatom in use_data:
1946 mymatch = self.match_package(myatom)
1947 if mymatch != matched_atom:
1948 continue
1949 for flag in use_data[myatom]:
1950 if flag.startswith("-"):
1951 myflag = flag[1:]
1952 data['enabled'].discard(myflag)
1953 data['disabled'].add(myflag)
1954 else:
1955 myflag = flag
1956 if myflag.startswith("+"):
1957 myflag = myflag[1:]
1958 data['disabled'].discard(myflag)
1959 data['enabled'].add(myflag)
1960
1961 return data
1962
1964 return self.portage.settings['USE']
1965
1967 return self.portage.settings.useforce
1968
1970 return self.portage.settings.usemask
1971
1973 use = set()
1974 use_mask = self._get_useflags_mask()
1975 use_force = self._get_useflags_force()
1976 for myiuse in iuse_list:
1977 if myiuse[0] in ("+", "-",):
1978 myiuse = myiuse[1:]
1979 if ((myiuse in use_list) or (myiuse in use_force)) and \
1980 (myiuse not in use_mask):
1981 use.add(myiuse)
1982 return use
1983
1984 - def _calculate_dependencies(self, my_iuse, my_use, my_license, my_depend,
1985 my_rdepend, my_pdepend, my_provide, my_src_uri):
1986
1987 metadata = {
1988 'LICENSE': my_license,
1989 'DEPEND': my_depend,
1990 'PDEPEND': my_pdepend,
1991 'RDEPEND': my_rdepend,
1992 'PROVIDE': my_provide,
1993 'SRC_URI': my_src_uri,
1994 'USE_MASK': sorted(self._get_useflags_mask()),
1995 'USE_FORCE': sorted(self._get_useflags_force()),
1996 }
1997
1998 # generate USE flags metadata
1999 raw_use = my_use.split()
2000 enabled_use = sorted(self._resolve_enabled_useflags(
2001 my_iuse.split(), raw_use))
2002
2003 metadata['ENABLED_USE'] = enabled_use
2004 use = raw_use + [x for x in metadata['USE_FORCE'] if x not in raw_use]
2005 metadata['USE'] = sorted([unicode(x) for x in use if x not in \
2006 metadata['USE_MASK']])
2007
2008 for k in "LICENSE", "RDEPEND", "DEPEND", "PDEPEND", "PROVIDE", "SRC_URI":
2009 try:
2010 if k == "SRC_URI":
2011 deps = self._src_uri_paren_reduce(metadata[k])
2012 else:
2013 deps = self._paren_reduce(metadata[k])
2014 deps = self._use_reduce(deps, uselist = raw_use)
2015 deps = self.paren_normalize(deps)
2016 if k == "LICENSE":
2017 deps = self._paren_license_choose(deps)
2018 else:
2019 deps = self._paren_choose(deps)
2020 if k.endswith("DEPEND"):
2021 deps = self._usedeps_reduce(deps, enabled_use)
2022 deps = ' '.join(deps)
2023 except Exception, e:
2024 entropy.tools.print_traceback()
2025 self.updateProgress(
2026 darkred("%s: %s: %s :: %s") % (
2027 _("Error calculating dependencies"),
2028 str(Exception),
2029 k,
2030 e,
2031 ),
2032 importance = 1,
2033 type = "error",
2034 header = red(" !!! ")
2035 )
2036 deps = ''
2037 continue
2038 metadata[k] = deps
2039 return metadata
2040
2042 src_uris = self._paren_reduce(src_uris)
2043 newlist = []
2044 skip_next = False
2045 for src_uri in src_uris:
2046 if skip_next:
2047 skip_next = False
2048 continue
2049 if src_uri == "->":
2050 skip_next = True
2051 continue
2052 newlist.append(src_uri)
2053 return newlist
2054
2056 newlist = []
2057
2058 def strip_use(xuse):
2059 myuse = xuse[:]
2060 if myuse[0] == "!":
2061 myuse = myuse[1:]
2062 if myuse[-1] in ("=","?",):
2063 myuse = myuse[:-1]
2064 return myuse
2065
2066 for dependency in dependencies:
2067 use_deps = entropy.tools.dep_getusedeps(dependency)
2068 if use_deps:
2069 new_use_deps = []
2070 for use in use_deps:
2071 """
2072 explicitly support only specific types
2073 """
2074 if (use[0] == "!") and (use[-1] not in ("=","?",)):
2075 # this does not exist atm
2076 continue
2077 elif use[-1] == "=":
2078 if use[0] == "!":
2079 # foo[!bar=] means bar? ( foo[-bar] ) !bar? ( foo[bar] )
2080 s_use = strip_use(use)
2081 if s_use in enabled_useflags:
2082 new_use_deps.append("-%s" % (s_use,))
2083 else:
2084 new_use_deps.append(s_use)
2085 continue
2086 else:
2087 # foo[bar=] means bar? ( foo[bar] ) !bar? ( foo[-bar] )
2088 s_use = strip_use(use)
2089 if s_use in enabled_useflags:
2090 new_use_deps.append(s_use)
2091 else:
2092 new_use_deps.append("-%s" % (s_use,))
2093 continue
2094 elif use[-1] == "?":
2095 if use[0] == "!":
2096 # foo[!bar?] means bar? ( foo ) !bar? ( foo[-bar] )
2097 s_use = strip_use(use)
2098 if s_use not in enabled_useflags:
2099 new_use_deps.append("-%s" % (s_use,))
2100 continue
2101 else:
2102 # foo[bar?] means bar? ( foo[bar] ) !bar? ( foo )
2103 s_use = strip_use(use)
2104 if s_use in enabled_useflags:
2105 new_use_deps.append(s_use)
2106 continue
2107 new_use_deps.append(use)
2108
2109 if new_use_deps:
2110 dependency = "%s[%s]" % (
2111 entropy.tools.remove_usedeps(dependency),
2112 ','.join(new_use_deps),
2113 )
2114 else:
2115 dependency = entropy.tools.remove_usedeps(dependency)
2116
2117 newlist.append(dependency)
2118 return newlist
2119
2121 """
2122
2123 # deps.py -- Portage dependency resolution functions
2124 # Copyright 2003-2004 Gentoo Foundation
2125 # Distributed under the terms of the GNU General Public License v2
2126 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $
2127
2128 Take a string and convert all paren enclosed entities into sublists, optionally
2129 futher splitting the list elements by spaces.
2130
2131 Example usage:
2132 >>> paren_reduce('foobar foo ( bar baz )',1)
2133 ['foobar', 'foo', ['bar', 'baz']]
2134 >>> paren_reduce('foobar foo ( bar baz )',0)
2135 ['foobar foo ', [' bar baz ']]
2136
2137 @param mystr: The string to reduce
2138 @type mystr: String
2139 @rtype: Array
2140 @return: The reduced string in an array
2141 """
2142 mylist = []
2143 while mystr:
2144 left_paren = mystr.find("(")
2145 has_left_paren = left_paren != -1
2146 right_paren = mystr.find(")")
2147 has_right_paren = right_paren != -1
2148 if not has_left_paren and not has_right_paren:
2149 freesec = mystr
2150 subsec = None
2151 tail = ""
2152 elif mystr[0] == ")":
2153 return [mylist,mystr[1:]]
2154 elif has_left_paren and not has_right_paren:
2155 raise InvalidDependString(
2156 "InvalidDependString: %s: '%s'" % (_("missing right parenthesis"),mystr,))
2157 elif has_left_paren and left_paren < right_paren:
2158 freesec,subsec = mystr.split("(",1)
2159 subsec,tail = self._paren_reduce(subsec)
2160 else:
2161 subsec,tail = mystr.split(")",1)
2162 subsec = self._strip_empty(subsec.split(" "))
2163 return [mylist+subsec,tail]
2164 mystr = tail
2165 if freesec:
2166 mylist = mylist + self._strip_empty(freesec.split(" "))
2167 if subsec is not None:
2168 mylist = mylist + [subsec]
2169 return mylist
2170
2172 """
2173
2174 # deps.py -- Portage dependency resolution functions
2175 # Copyright 2003-2004 Gentoo Foundation
2176 # Distributed under the terms of the GNU General Public License v2
2177 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $
2178
2179 Strip all empty elements from an array
2180
2181 @param myarr: The list of elements
2182 @type myarr: List
2183 @rtype: Array
2184 @return: The array with empty elements removed
2185 """
2186 for x in range(len(myarr)-1, -1, -1):
2187 if not myarr[x]:
2188 del myarr[x]
2189 return myarr
2190
2191 - def _use_reduce(self, deparray, uselist = None, masklist = None,
2192 matchall = 0, excludeall = None):
2193 """
2194
2195 # deps.py -- Portage dependency resolution functions
2196 # Copyright 2003-2004 Gentoo Foundation
2197 # Distributed under the terms of the GNU General Public License v2
2198 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $
2199
2200 Takes a paren_reduce'd array and reduces the use? conditionals out
2201 leaving an array with subarrays
2202
2203 @param deparray: paren_reduce'd list of deps
2204 @type deparray: List
2205 @param uselist: List of use flags
2206 @type uselist: List
2207 @param masklist: List of masked flags
2208 @type masklist: List
2209 @param matchall: Resolve all conditional deps unconditionally. Used by repoman
2210 @type matchall: Integer
2211 @rtype: List
2212 @return: The use reduced depend array
2213 """
2214
2215 if uselist is None:
2216 uselist = []
2217 if masklist is None:
2218 masklist = []
2219 if excludeall is None:
2220 excludeall = []
2221
2222 # Quick validity checks
2223 for x in range(len(deparray)):
2224 if deparray[x] in ["||","&&"]:
2225 if len(deparray) - 1 == x or not isinstance(deparray[x+1], list):
2226 mytxt = _("missing atom list in")
2227 raise InvalidDependString(deparray[x]+" "+mytxt+" \""+str(deparray)+"\"")
2228 if deparray and deparray[-1] and deparray[-1][-1] == "?":
2229 mytxt = _("Conditional without target in")
2230 raise InvalidDependString("InvalidDependString: "+mytxt+" \""+str(deparray)+"\"")
2231
2232 # This is just for use by emerge so that it can enable a backward compatibility
2233 # mode in order to gracefully deal with installed packages that have invalid
2234 # atoms or dep syntax. For backward compatibility with api consumers, strict
2235 # behavior will be explicitly enabled as necessary.
2236 _dep_check_strict = False
2237
2238 mydeparray = deparray[:]
2239 rlist = []
2240 while mydeparray:
2241 head = mydeparray.pop(0)
2242
2243 if isinstance(head,list):
2244 additions = self._use_reduce(head, uselist, masklist, matchall, excludeall)
2245 if additions:
2246 rlist.append(additions)
2247 elif rlist and rlist[-1] == "||":
2248 #XXX: Currently some DEPEND strings have || lists without default atoms.
2249 # raise portage_exception.InvalidDependString("No default atom(s) in \""+paren_enclose(deparray)+"\"")
2250 rlist.append([])
2251 else:
2252 if head[-1] == "?": # Use reduce next group on fail.
2253 # Pull any other use conditions and the following atom or list into a separate array
2254 newdeparray = [head]
2255 while isinstance(newdeparray[-1], basestring) and newdeparray[-1][-1] == "?":
2256 if mydeparray:
2257 newdeparray.append(mydeparray.pop(0))
2258 else:
2259 raise ValueError, _("Conditional with no target")
2260
2261 # Deprecation checks
2262 warned = 0
2263 if len(newdeparray[-1]) == 0:
2264 mytxt = "%s. (%s)" % (_("Empty target in string"),_("Deprecated"),)
2265 self.updateProgress(
2266 darkred("PortagePlugin._use_reduce(): %s" % (mytxt,)),
2267 importance = 0,
2268 type = "error",
2269 header = bold(" !!! ")
2270 )
2271 warned = 1
2272 if len(newdeparray) != 2:
2273 mytxt = "%s. (%s)" % (_("Nested use flags without parenthesis"),_("Deprecated"),)
2274 self.updateProgress(
2275 darkred("PortagePlugin._use_reduce(): %s" % (mytxt,)),
2276 importance = 0,
2277 type = "error",
2278 header = bold(" !!! ")
2279 )
2280 warned = 1
2281 if warned:
2282 self.updateProgress(
2283 darkred("PortagePlugin._use_reduce(): "+" ".join(map(str,[head]+newdeparray))),
2284 importance = 0,
2285 type = "error",
2286 header = bold(" !!! ")
2287 )
2288
2289 # Check that each flag matches
2290 ismatch = True
2291 missing_flag = False
2292 for head in newdeparray[:-1]:
2293 head = head[:-1]
2294 if not head:
2295 missing_flag = True
2296 break
2297 if head.startswith("!"):
2298 head_key = head[1:]
2299 if not head_key:
2300 missing_flag = True
2301 break
2302 if not matchall and head_key in uselist or \
2303 head_key in excludeall:
2304 ismatch = False
2305 break
2306 elif head not in masklist:
2307 if not matchall and head not in uselist:
2308 ismatch = False
2309 break
2310 else:
2311 ismatch = False
2312 if missing_flag:
2313 mytxt = _("Conditional without flag")
2314 raise InvalidDependString(
2315 "InvalidDependString: "+mytxt+": \"" + \
2316 str([head+"?", newdeparray[-1]])+"\"")
2317
2318 # If they all match, process the target
2319 if ismatch:
2320 target = newdeparray[-1]
2321 if isinstance(target, list):
2322 additions = self._use_reduce(target, uselist, masklist, matchall, excludeall)
2323 if additions:
2324 rlist.append(additions)
2325 elif not _dep_check_strict:
2326 # The old deprecated behavior.
2327 rlist.append(target)
2328 else:
2329 mytxt = _("Conditional without parenthesis")
2330 raise InvalidDependString(
2331 "InvalidDependString: "+mytxt+": '%s?'" % head)
2332
2333 else:
2334 rlist += [head]
2335 return rlist
2336
2338 newlist = []
2339 do_skip = False
2340 for idx in range(len(dep_list)):
2341
2342 if do_skip:
2343 do_skip = False
2344 continue
2345
2346 item = dep_list[idx]
2347 if item == "||": # or
2348 next_item = dep_list[idx+1]
2349 if not next_item: # || ( asd? ( atom ) dsa? ( atom ) ) => [] if use asd and dsa are disabled
2350 do_skip = True
2351 continue
2352 item = self._dep_or_select(next_item) # must be a list
2353 if not item:
2354 # no matches, transform to string and append, so reagent will fail
2355 newlist.append(str(next_item))
2356 else:
2357 newlist += item
2358 do_skip = True
2359 elif isinstance(item, list): # and
2360 item = self._dep_and_select(item)
2361 newlist += item
2362 else:
2363 newlist.append(item)
2364
2365 return newlist
2366
2368 do_skip = False
2369 newlist = []
2370 for idx in range(len(and_list)):
2371
2372 if do_skip:
2373 do_skip = False
2374 continue
2375
2376 x = and_list[idx]
2377 if x == "||":
2378 x = self._dep_or_select(and_list[idx+1])
2379 do_skip = True
2380 if not x:
2381 x = str(and_list[idx+1])
2382 else:
2383 newlist += x
2384 elif isinstance(x, list):
2385 x = self._dep_and_select(x)
2386 newlist += x
2387 else:
2388 newlist.append(x)
2389
2390 # now verify if all are satisfied
2391 for x in newlist:
2392 match = self.match_installed_package(x)
2393 if not match:
2394 return []
2395
2396 return newlist
2397
2399 do_skip = False
2400 for idx in range(len(or_list)):
2401 if do_skip:
2402 do_skip = False
2403 continue
2404 x = or_list[idx]
2405 if x == "||": # or
2406 x = self._dep_or_select(or_list[idx+1])
2407 do_skip = True
2408 elif isinstance(x, list): # and
2409 x = self._dep_and_select(x)
2410 if not x:
2411 continue
2412 # found
2413 return x
2414 else:
2415 x = [x]
2416
2417 for y in x:
2418 match = self.match_installed_package(y)
2419 if match:
2420 return [y]
2421
2422 return []
2423
2425
2426 newlist = set()
2427 for item in dep_list:
2428
2429 if isinstance(item, list):
2430 # match the first
2431 data = set(self._paren_license_choose(item))
2432 newlist.update(data)
2433 else:
2434 if item not in ["||"]:
2435 newlist.add(item)
2436
2437 return list(newlist)
2438
2440 if root is None:
2441 root = etpConst['systemroot'] + os.path.sep
2442 return os.path.join(root, self.portage_const.VDB_PATH)
2443
2445
2446 # from portage.const import USER_CONFIG_PATH, GLOBAL_CONFIG_PATH
2447 setconfigpaths = [os.path.join(self.portage_const.GLOBAL_CONFIG_PATH, etpConst['setsconffilename'])]
2448 setconfigpaths.append(os.path.join(settings["PORTDIR"], etpConst['setsconffilename']))
2449 setconfigpaths += [os.path.join(x, etpConst['setsconffilename']) for x in settings["PORTDIR_OVERLAY"].split()]
2450 setconfigpaths.append(os.path.join(settings["PORTAGE_CONFIGROOT"],
2451 self.portage_const.USER_CONFIG_PATH.lstrip(os.path.sep), etpConst['setsconffilename']))
2452 return self.portage_sets.SetConfig(setconfigpaths, settings, trees)
2453
2455 # old portage
2456 if self.portage_sets == None:
2457 return
2458 myroot = etpConst['systemroot'] + os.path.sep
2459 return self._load_sets_config(
2460 self.portage.settings,
2461 self.portage.db[myroot]
2462 )
2463
2465 data = {
2466 'pf': {
2467 'path': etpConst['spm']['xpak_entries']['pf'],
2468 'critical': True,
2469 },
2470 'chost': {
2471 'path': etpConst['spm']['xpak_entries']['chost'],
2472 'critical': True,
2473 },
2474 'description': {
2475 'path': etpConst['spm']['xpak_entries']['description'],
2476 'critical': False,
2477 },
2478 'homepage': {
2479 'path': etpConst['spm']['xpak_entries']['homepage'],
2480 'critical': False,
2481 },
2482 'slot': {
2483 'path': etpConst['spm']['xpak_entries']['slot'],
2484 'critical': False,
2485 },
2486 'cflags': {
2487 'path': etpConst['spm']['xpak_entries']['cflags'],
2488 'critical': False,
2489 },
2490 'cxxflags': {
2491 'path': etpConst['spm']['xpak_entries']['cxxflags'],
2492 'critical': False,
2493 },
2494 'category': {
2495 'path': etpConst['spm']['xpak_entries']['category'],
2496 'critical': True,
2497 },
2498 'rdepend': {
2499 'path': etpConst['spm']['xpak_entries']['rdepend'],
2500 'critical': False,
2501 },
2502 'pdepend': {
2503 'path': etpConst['spm']['xpak_entries']['pdepend'],
2504 'critical': False,
2505 },
2506 'depend': {
2507 'path': etpConst['spm']['xpak_entries']['depend'],
2508 'critical': False,
2509 },
2510 'use': {
2511 'path': etpConst['spm']['xpak_entries']['use'],
2512 'critical': False,
2513 },
2514 'iuse': {
2515 'path': etpConst['spm']['xpak_entries']['iuse'],
2516 'critical': False,
2517 },
2518 'license': {
2519 'path': etpConst['spm']['xpak_entries']['license'],
2520 'critical': False,
2521 },
2522 'provide': {
2523 'path': etpConst['spm']['xpak_entries']['provide'],
2524 'critical': False,
2525 },
2526 'sources': {
2527 'path': etpConst['spm']['xpak_entries']['src_uri'],
2528 'critical': False,
2529 },
2530 'eclasses': {
2531 'path': etpConst['spm']['xpak_entries']['inherited'],
2532 'critical': False,
2533 },
2534 'counter': {
2535 'path': etpConst['spm']['xpak_entries']['counter'],
2536 'critical': False,
2537 },
2538 'keywords': {
2539 'path': etpConst['spm']['xpak_entries']['keywords'],
2540 'critical': False,
2541 },
2542 'spm_phases': {
2543 'path': etpConst['spm']['xpak_entries']['defined_phases'],
2544 'critical': False,
2545 },
2546 }
2547 return data
2548
2550
2551 pkg_content = {}
2552
2553 if os.path.isfile(content_file):
2554
2555 f = open(content_file,"r")
2556 content = [x.decode('raw_unicode_escape') for x in f.readlines()]
2557 f.close()
2558 outcontent = set()
2559 for line in content:
2560 line = line.strip().split()
2561 try:
2562 datatype = line[0]
2563 datafile = line[1:]
2564 if datatype == 'obj':
2565 datafile = datafile[:-2]
2566 datafile = ' '.join(datafile)
2567 elif datatype == 'dir':
2568 datafile = ' '.join(datafile)
2569 elif datatype == 'sym':
2570 datafile = datafile[:-3]
2571 datafile = ' '.join(datafile)
2572 else:
2573 myexc = "InvalidData: %s %s. %s." % (
2574 datafile,
2575 _("not supported"),
2576 _("Probably Portage API has changed"),
2577 )
2578 raise InvalidData(myexc)
2579 outcontent.add((datafile,datatype))
2580 except:
2581 pass
2582
2583 outcontent = sorted(outcontent)
2584 for datafile, datatype in outcontent:
2585 pkg_content[datafile] = datatype
2586
2587 else:
2588
2589 # CONTENTS is not generated when a package is emerged with portage and the option -B
2590 # we have to unpack the tbz2 and generate content dict
2591 mytempdir = etpConst['packagestmpdir']+"/"+os.path.basename(package_path)+".inject"
2592 if os.path.isdir(mytempdir):
2593 shutil.rmtree(mytempdir)
2594 if not os.path.isdir(mytempdir):
2595 os.makedirs(mytempdir)
2596
2597 entropy.tools.uncompress_tar_bz2(package_path, extractPath = mytempdir, catchEmpty = True)
2598 tmpdir_len = len(mytempdir)
2599 for currentdir, subdirs, files in os.walk(mytempdir):
2600 pkg_content[currentdir[tmpdir_len:]] = u"dir"
2601 for item in files:
2602 item = currentdir+"/"+item
2603 if os.path.islink(item):
2604 pkg_content[item[tmpdir_len:]] = u"sym"
2605 else:
2606 pkg_content[item[tmpdir_len:]] = u"obj"
2607
2608 # now remove
2609 shutil.rmtree(mytempdir,True)
2610 try:
2611 os.rmdir(mytempdir)
2612 except (OSError,):
2613 pass
2614
2615 return pkg_content
2616
2618
2619 pkg_needed = set()
2620 lines = []
2621
2622 try:
2623 f = open(needed_file,"r")
2624 lines = [x.decode('raw_unicode_escape').strip() for x in f.readlines() if x.strip()]
2625 f.close()
2626 except IOError:
2627 return lines
2628
2629 for line in lines:
2630 needed = line.split()
2631 if len(needed) == 2:
2632 ownlib = needed[0]
2633 ownelf = -1
2634 if os.access(ownlib,os.R_OK):
2635 ownelf = entropy.tools.read_elf_class(ownlib)
2636 for lib in needed[1].split(","):
2637 #if lib.find(".so") != -1:
2638 pkg_needed.add((lib,ownelf))
2639
2640 return sorted(pkg_needed)
2641
2643
2644 data = {}
2645 ldpaths = entropy.tools.collect_linker_paths()
2646
2647 for needed_lib, elf_class in needed_libs:
2648 for ldpath in ldpaths:
2649 my_lib = os.path.join(ldpath, needed_lib)
2650 if not os.access(my_lib, os.R_OK):
2651 continue
2652 myclass = entropy.tools.read_elf_class(my_lib)
2653 if myclass != elf_class:
2654 continue
2655 obj = data.setdefault(needed_lib, set())
2656 obj.add((my_lib, myclass,))
2657
2658 return data
2659
2661
2662 pkg_messages = []
2663 if not os.path.isdir(log_dir):
2664 return pkg_messages
2665
2666 elogfiles = os.listdir(log_dir)
2667 myelogfile = "%s:%s-%s" % (category, name, version,)
2668 foundfiles = [x for x in elogfiles if x.startswith(myelogfile)]
2669 if foundfiles:
2670 elogfile = foundfiles[0]
2671 if len(foundfiles) > 1:
2672 # get the latest
2673 mtimes = []
2674 for item in foundfiles: mtimes.append((entropy.tools.get_file_unix_mtime(os.path.join(log_dir,item)),item))
2675 mtimes = sorted(mtimes)
2676 elogfile = mtimes[-1][1]
2677 messages = entropy.tools.extract_elog(os.path.join(log_dir,elogfile))
2678 for message in messages:
2679 message = message.replace("emerge","install")
2680 pkg_messages.append(message.decode('raw_unicode_escape'))
2681
2682 return pkg_messages
2683
2685
2686 pkg_licensedata = {}
2687 if licenses_dir and os.path.isdir(licenses_dir):
2688 licdata = [x.strip() for x in license_string.split() if x.strip() and entropy.tools.is_valid_string(x.strip())]
2689 for mylicense in licdata:
2690 licfile = os.path.join(licenses_dir,mylicense)
2691 if os.access(licfile,os.R_OK):
2692 if entropy.tools.istextfile(licfile):
2693 f = open(licfile)
2694 content = ''
2695 line = f.readline()
2696 while line:
2697 content += line
2698 line = f.readline()
2699 try:
2700 try:
2701 pkg_licensedata[mylicense] = content.decode('raw_unicode_escape')
2702 except UnicodeDecodeError:
2703 pkg_licensedata[mylicense] = unicode(content,'utf-8')
2704 except (UnicodeDecodeError, UnicodeEncodeError,):
2705 continue # sorry!
2706 f.close()
2707
2708 return pkg_licensedata
2709
2711
2712 # =mirror://openoffice|link1|link2|link3
2713 pkg_links = []
2714 for i in sources_list:
2715 if i.startswith("mirror://"):
2716 # parse what mirror I need
2717 mirrorURI = i.split("/")[2]
2718 mirrorlist = set(self.get_download_mirrors(mirrorURI))
2719 pkg_links.append([mirrorURI,mirrorlist])
2720 # mirrorURI = openoffice and mirrorlist = [link1, link2, link3]
2721
2722 return pkg_links
2723
2725 search_tag = etpConst['spm']['ebuild_pkg_tag_var']
2726 ebuild_tag = ''
2727 f = open(ebuild,"r")
2728 tags = [x.strip().decode('raw_unicode_escape') for x in f.readlines() if x.strip() and x.strip().startswith(search_tag)]
2729 f.close()
2730 if not tags: return ebuild_tag
2731 tag = tags[-1]
2732 tag = tag.split("=")[-1].strip('"').strip("'").strip()
2733 return tag
2734
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Fri Sep 4 11:50:19 2009 | http://epydoc.sourceforge.net |