1
2
3
4 from __future__ import unicode_literals
5
6 import io
7
8 import portage
9 from portage import os
10 from portage.dep import Atom, _repo_name_re
11 from portage.eapi import eapi_has_repo_deps
12 from portage.elog import messages as elog_messages
13 from portage.exception import InvalidAtom
14 from portage.package.ebuild._ipc.IpcCommand import IpcCommand
15 from portage.util import normalize_path
16 from portage.versions import best
19
20 __slots__ = ('phase', 'settings',)
21
22 _db = None
23
24 @classmethod
29
34
36 """
37 @return: tuple of (stdout, stderr, returncode)
38 """
39
40
41
42 cmd = argv[0]
43 root = argv[1]
44 args = argv[2:]
45
46 warnings = []
47 warnings_str = ''
48
49 db = self.get_db()
50 eapi = self.settings.get('EAPI')
51
52 root = normalize_path(root).rstrip(os.path.sep) + os.path.sep
53 if root not in db:
54 return ('', '%s: Invalid ROOT: %s\n' % (cmd, root), 3)
55
56 portdb = db[root]["porttree"].dbapi
57 vardb = db[root]["vartree"].dbapi
58
59 if cmd in ('best_version', 'has_version'):
60 allow_repo = eapi_has_repo_deps(eapi)
61 try:
62 atom = Atom(args[0], allow_repo=allow_repo)
63 except InvalidAtom:
64 return ('', '%s: Invalid atom: %s\n' % (cmd, args[0]), 2)
65
66 try:
67 atom = Atom(args[0], allow_repo=allow_repo, eapi=eapi)
68 except InvalidAtom as e:
69 warnings.append("QA Notice: %s: %s" % (cmd, e))
70
71 use = self.settings.get('PORTAGE_BUILT_USE')
72 if use is None:
73 use = self.settings['PORTAGE_USE']
74
75 use = frozenset(use.split())
76 atom = atom.evaluate_conditionals(use)
77
78 if warnings:
79 warnings_str = self._elog('eqawarn', warnings)
80
81 if cmd == 'has_version':
82 if vardb.match(atom):
83 returncode = 0
84 else:
85 returncode = 1
86 return ('', warnings_str, returncode)
87 elif cmd == 'best_version':
88 m = best(vardb.match(atom))
89 return ('%s\n' % m, warnings_str, 0)
90 elif cmd in ('master_repositories', 'repository_path', 'available_eclasses', 'eclass_path', 'license_path'):
91 repo = _repo_name_re.match(args[0])
92 if repo is None:
93 return ('', '%s: Invalid repository: %s\n' % (cmd, args[0]), 2)
94 try:
95 repo = portdb.repositories[args[0]]
96 except KeyError:
97 return ('', warnings_str, 1)
98
99 if cmd == 'master_repositories':
100 return ('%s\n' % ' '.join(x.name for x in repo.masters), warnings_str, 0)
101 elif cmd == 'repository_path':
102 return ('%s\n' % repo.location, warnings_str, 0)
103 elif cmd == 'available_eclasses':
104 return ('%s\n' % ' '.join(sorted(repo.eclass_db.eclasses)), warnings_str, 0)
105 elif cmd == 'eclass_path':
106 try:
107 eclass = repo.eclass_db.eclasses[args[1]]
108 except KeyError:
109 return ('', warnings_str, 1)
110 return ('%s\n' % eclass.location, warnings_str, 0)
111 elif cmd == 'license_path':
112 paths = reversed([os.path.join(x.location, 'licenses', args[1]) for x in list(repo.masters) + [repo]])
113 for path in paths:
114 if os.path.exists(path):
115 return ('%s\n' % path, warnings_str, 0)
116 return ('', warnings_str, 1)
117 else:
118 return ('', 'Invalid command: %s\n' % cmd, 3)
119
120 - def _elog(self, elog_funcname, lines):
121 """
122 This returns a string, to be returned via ipc and displayed at the
123 appropriate place in the build output. We wouldn't want to open the
124 log here since it is already opened by AbstractEbuildProcess and we
125 don't want to corrupt it, especially if it is being written with
126 compression.
127 """
128 out = io.StringIO()
129 phase = self.phase
130 elog_func = getattr(elog_messages, elog_funcname)
131 global_havecolor = portage.output.havecolor
132 try:
133 portage.output.havecolor = \
134 self.settings.get('NOCOLOR', 'false').lower() in ('no', 'false')
135 for line in lines:
136 elog_func(line, phase=phase, key=self.settings.mycpv, out=out)
137 finally:
138 portage.output.havecolor = global_havecolor
139 msg = out.getvalue()
140 return msg
141