2 # Copyright 1999-2014 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
5 from __future__ import print_function
10 # This block ensures that ^C interrupts are handled quietly.
13 def exithandler(signum, _frame):
14 signal.signal(signal.SIGINT, signal.SIG_IGN)
15 signal.signal(signal.SIGTERM, signal.SIG_IGN)
16 sys.exit(128 + signum)
18 signal.signal(signal.SIGINT, exithandler)
19 signal.signal(signal.SIGTERM, exithandler)
20 # Prevent "[Errno 32] Broken pipe" exceptions when
22 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
24 except KeyboardInterrupt:
25 sys.exit(128 + signal.SIGINT)
27 def debug_signal(_signum, _frame):
31 if platform.python_implementation() == 'Jython':
32 debug_signum = signal.SIGUSR2 # bug #424259
34 debug_signum = signal.SIGUSR1
36 signal.signal(debug_signum, debug_signal)
40 from os import path as osp
41 pym_path = osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym")
42 sys.path.insert(0, pym_path)
44 portage._internal_caller = True
45 from portage import os
46 from portage import _encodings
47 from portage import _shell_quote
48 from portage import _unicode_decode
49 from portage import _unicode_encode
50 from portage.const import VDB_PATH
51 from portage.util._argparse import ArgumentParser
52 from _emerge.Package import Package
53 from _emerge.RootConfig import RootConfig
55 description = "See the ebuild(1) man page for more info"
56 usage = "Usage: ebuild <ebuild file> <command> [command] ..."
57 parser = ArgumentParser(description=description, usage=usage)
59 force_help = "When used together with the digest or manifest " + \
60 "command, this option forces regeneration of digests for all " + \
61 "distfiles associated with the current ebuild. Any distfiles " + \
62 "that do not already exist in ${DISTDIR} will be automatically fetched."
64 parser.add_argument("--force", help=force_help, action="store_true")
65 parser.add_argument("--color", help="enable or disable color output",
67 parser.add_argument("--debug", help="show debug output",
69 parser.add_argument("--version", help="show version and exit",
71 parser.add_argument("--ignore-default-opts",
73 help="do not use the EBUILD_DEFAULT_OPTS environment variable")
74 parser.add_argument("--skip-manifest", help="skip all manifest checks",
77 opts, pargs = parser.parse_known_args(args=sys.argv[1:])
80 portage.writemsg('ebuild: %s\n' % (txt,), noiselevel=-1)
84 print("Portage", portage.VERSION)
88 parser.error("missing required args")
90 if not opts.ignore_default_opts:
91 default_opts = portage.util.shlex_split(
92 portage.settings.get("EBUILD_DEFAULT_OPTS", ""))
93 opts, pargs = parser.parse_known_args(default_opts + sys.argv[1:])
98 import portage.util, portage.const
100 # do this _after_ 'import portage' to prevent unnecessary tracing
101 if debug and "python-trace" in portage.features:
103 portage.debug.set_trace(True)
105 if not opts.color == 'y' and \
106 (opts.color == 'n' or \
107 portage.settings.get('NOCOLOR') in ('yes', 'true') or \
108 portage.settings.get('TERM') == 'dumb' or \
109 not sys.stdout.isatty()):
110 portage.output.nocolor()
111 portage.settings.unlock()
112 portage.settings['NOCOLOR'] = 'true'
113 portage.settings.lock()
115 ebuild = pargs.pop(0)
118 if ebuild.endswith(".ebuild"):
119 pf = os.path.basename(ebuild)[:-7]
122 err("%s: does not end with '.ebuild'" % (ebuild,))
124 if not os.path.isabs(ebuild):
126 # Try to get the non-canonical path from the PWD evironment variable, since
127 # the canonical path returned from os.getcwd() may may be unusable in
128 # cases where the directory stucture is built from symlinks.
129 pwd = os.environ.get('PWD', '')
130 if sys.hexversion < 0x3000000:
131 pwd = _unicode_decode(pwd, encoding=_encodings['content'],
133 if pwd and pwd != mycwd and \
134 os.path.realpath(pwd) == mycwd:
135 mycwd = portage.normalize_path(pwd)
136 ebuild = os.path.join(mycwd, ebuild)
137 ebuild = portage.normalize_path(ebuild)
138 # portdbapi uses the canonical path for the base of the portage tree, but
139 # subdirectories of the base can be built from symlinks (like crossdev does).
140 ebuild_portdir = os.path.realpath(
141 os.path.dirname(os.path.dirname(os.path.dirname(ebuild))))
142 ebuild = os.path.join(ebuild_portdir, *ebuild.split(os.path.sep)[-3:])
143 vdb_path = os.path.realpath(os.path.join(portage.settings['EROOT'], VDB_PATH))
145 # Make sure that portdb.findname() returns the correct ebuild.
146 if ebuild_portdir != vdb_path and \
147 ebuild_portdir not in portage.portdb.porttrees:
148 portdir_overlay = portage.settings.get("PORTDIR_OVERLAY", "")
149 if sys.hexversion >= 0x3000000:
150 os.environ["PORTDIR_OVERLAY"] = \
152 " " + _shell_quote(ebuild_portdir)
154 os.environ["PORTDIR_OVERLAY"] = \
155 _unicode_encode(portdir_overlay,
156 encoding=_encodings['content'], errors='strict') + \
157 " " + _unicode_encode(_shell_quote(ebuild_portdir),
158 encoding=_encodings['content'], errors='strict')
160 print("Appending %s to PORTDIR_OVERLAY..." % ebuild_portdir)
161 portage._reset_legacy_globals()
164 if ebuild_portdir != vdb_path:
165 myrepo = portage.portdb.getRepositoryName(ebuild_portdir)
167 if not os.path.exists(ebuild):
168 err('%s: does not exist' % (ebuild,))
170 ebuild_split = ebuild.split("/")
171 cpv = "%s/%s" % (ebuild_split[-3], pf)
173 with io.open(_unicode_encode(ebuild, encoding=_encodings['fs'], errors='strict'),
174 mode='r', encoding=_encodings['repo.content'], errors='replace') as f:
175 eapi = portage._parse_eapi_ebuild_head(f)[0]
178 if not portage.catpkgsplit(cpv, eapi=eapi):
179 err('%s: %s: does not follow correct package syntax' % (ebuild, cpv))
181 if ebuild.startswith(vdb_path):
183 pkg_type = "installed"
185 portage_ebuild = portage.db[portage.root][mytree].dbapi.findname(cpv, myrepo=myrepo)
187 if os.path.realpath(portage_ebuild) != ebuild:
188 err('Portage seems to think that %s is at %s' % (cpv, portage_ebuild))
194 portage_ebuild = portage.portdb.findname(cpv, myrepo=myrepo)
196 if not portage_ebuild or portage_ebuild != ebuild:
197 err('%s: does not seem to have a valid PORTDIR structure' % (ebuild,))
199 if len(pargs) > 1 and "config" in pargs:
200 err('"config" must not be called with any other phase')
202 def discard_digests(myebuild, mysettings, mydbapi):
203 """Discard all distfiles digests for the given ebuild. This is useful when
204 upstream has changed the identity of the distfiles and the user would
205 otherwise have to manually remove the Manifest and files/digest-* files in
206 order to ensure correct results."""
208 portage._doebuild_manifest_exempt_depend += 1
209 pkgdir = os.path.dirname(myebuild)
210 fetchlist_dict = portage.FetchlistDict(pkgdir, mysettings, mydbapi)
211 mf = mysettings.repositories.get_repo_for_location(
212 os.path.dirname(os.path.dirname(pkgdir)))
213 mf = mf.load_manifest(pkgdir, mysettings["DISTDIR"],
214 fetchlist_dict=fetchlist_dict)
215 mf.create(requiredDistfiles=None,
216 assumeDistHashesSometimes=True, assumeDistHashesAlways=True)
217 distfiles = fetchlist_dict[cpv]
218 for myfile in distfiles:
220 del mf.fhashdict["DIST"][myfile]
225 portage._doebuild_manifest_exempt_depend -= 1
227 portage.settings.validate() # generate warning messages if necessary
229 build_dir_phases = set(["setup", "unpack", "prepare", "configure", "compile",
230 "test", "install", "package", "rpm", "merge", "qmerge"])
232 # If the current metadata is invalid then force the ebuild to be
233 # sourced again even if $T/environment already exists.
234 ebuild_changed = False
235 if mytree == "porttree" and build_dir_phases.intersection(pargs):
237 portage.portdb._pull_valid_cache(cpv, ebuild, ebuild_portdir)[0] is None
239 tmpsettings = portage.config(clone=portage.settings)
240 tmpsettings["PORTAGE_VERBOSE"] = "1"
241 tmpsettings.backup_changes("PORTAGE_VERBOSE")
243 if opts.skip_manifest:
244 tmpsettings["EBUILD_SKIP_MANIFEST"] = "1"
245 tmpsettings.backup_changes("EBUILD_SKIP_MANIFEST")
247 if opts.skip_manifest or \
248 "digest" in tmpsettings.features or \
249 "digest" in pargs or \
251 portage._doebuild_manifest_exempt_depend += 1
254 # This variable is a signal to config.regenerate() to
255 # indicate that the test phase should be enabled regardless
256 # of problems such as masked "test" USE flag.
257 tmpsettings["EBUILD_FORCE_TEST"] = "1"
258 tmpsettings.backup_changes("EBUILD_FORCE_TEST")
259 tmpsettings.features.add("test")
261 tmpsettings.features.discard("fail-clean")
263 if "merge" in pargs and "noauto" in tmpsettings.features:
264 print("Disabling noauto in features... merge disables it. (qmerge doesn't)")
265 tmpsettings.features.discard("noauto")
268 metadata = dict(zip(Package.metadata_keys,
269 portage.db[portage.settings['EROOT']][mytree].dbapi.aux_get(
270 cpv, Package.metadata_keys, myrepo=myrepo)))
272 # aux_get failure, message should have been shown on stderr.
275 root_config = RootConfig(portage.settings,
276 portage.db[portage.settings['EROOT']], None)
278 pkg = Package(built=(pkg_type != "ebuild"), cpv=cpv,
279 installed=(pkg_type=="installed"),
280 metadata=metadata, root_config=root_config,
283 # Apply package.env and repo-level settings. This allows per-package
284 # FEATURES and other variables (possibly PORTAGE_TMPDIR) to be
285 # available as soon as possible. Also, note that the only way to ensure
286 # that setcpv gets metadata from the correct repository is to pass in
287 # a Package instance, as we do here (previously we had to modify
288 # portdb.porttrees in order to accomplish this).
289 tmpsettings.setcpv(pkg)
291 def stale_env_warning():
292 if "clean" not in pargs and \
293 "noauto" not in tmpsettings.features and \
294 build_dir_phases.intersection(pargs):
295 portage.doebuild_environment(ebuild, "setup", portage.root,
296 tmpsettings, debug, 1, portage.portdb)
297 env_filename = os.path.join(tmpsettings["T"], "environment")
298 if os.path.exists(env_filename):
299 msg = ("Existing ${T}/environment for '%s' will be sourced. " + \
300 "Run 'clean' to start with a fresh environment.") % \
301 (tmpsettings["PF"], )
302 from textwrap import wrap
305 portage.writemsg(">>> %s\n" % x)
308 open(os.path.join(tmpsettings['PORTAGE_BUILDDIR'],
309 '.ebuild_changed'), 'w').close()
311 from portage.exception import PermissionDenied, \
312 PortagePackageException, UnsupportedAPIException
314 if 'digest' in tmpsettings.features:
315 if pargs and pargs[0] not in ("digest", "manifest"):
316 pargs = ['digest'] + pargs
317 # We only need to build digests on the first pass.
318 tmpsettings.features.discard('digest')
320 checked_for_stale_env = False
324 if not checked_for_stale_env and arg not in ("digest","manifest"):
325 # This has to go after manifest generation since otherwise
326 # aux_get() might fail due to invalid ebuild digests.
328 checked_for_stale_env = True
330 if arg in ("digest", "manifest") and force:
331 discard_digests(ebuild, tmpsettings, portage.portdb)
332 a = portage.doebuild(ebuild, arg, settings=tmpsettings,
333 debug=debug, tree=mytree,
334 vartree=portage.db[portage.root]['vartree'])
335 except KeyboardInterrupt:
336 print("Interrupted.")
341 except UnsupportedAPIException as e:
342 from textwrap import wrap
343 msg = wrap(str(e), 70)
346 portage.writemsg("!!! %s\n" % x, noiselevel=-1)
348 except PortagePackageException as e:
349 portage.writemsg("!!! %s\n" % (e,), noiselevel=-1)
351 except PermissionDenied as e:
352 portage.writemsg("!!! Permission Denied: %s\n" % (e,), noiselevel=-1)
355 print("Could not run the required binary?")