2 # Copyright 1999-2013 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)
43 description = "See the ebuild(1) man page for more info"
44 usage = "Usage: ebuild <ebuild file> <command> [command] ..."
45 parser = optparse.OptionParser(description=description, usage=usage)
47 force_help = "When used together with the digest or manifest " + \
48 "command, this option forces regeneration of digests for all " + \
49 "distfiles associated with the current ebuild. Any distfiles " + \
50 "that do not already exist in ${DISTDIR} will be automatically fetched."
52 parser.add_option("--force", help=force_help, action="store_true", dest="force")
53 parser.add_option("--color", help="enable or disable color output",
54 type="choice", choices=("y", "n"))
55 parser.add_option("--debug", help="show debug output",
56 action="store_true", dest="debug")
57 parser.add_option("--version", help="show version and exit",
58 action="store_true", dest="version")
59 parser.add_option("--ignore-default-opts",
61 help="do not use the EBUILD_DEFAULT_OPTS environment variable")
62 parser.add_option("--skip-manifest", help="skip all manifest checks",
63 action="store_true", dest="skip_manifest")
65 opts, pargs = parser.parse_args(args=sys.argv[1:])
67 from os import path as osp
68 pym_path = osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym")
69 sys.path.insert(0, pym_path)
71 portage._internal_caller = True
72 from portage import os
73 from portage import _encodings
74 from portage import _shell_quote
75 from portage import _unicode_decode
76 from portage import _unicode_encode
77 from portage.const import VDB_PATH
78 from _emerge.Package import Package
79 from _emerge.RootConfig import RootConfig
82 print("Portage", portage.VERSION)
86 parser.error("missing required args")
88 if not opts.ignore_default_opts:
89 default_opts = portage.settings.get("EBUILD_DEFAULT_OPTS", "").split()
90 opts, pargs = parser.parse_args(default_opts + sys.argv[1:])
95 import portage.util, portage.const
97 # do this _after_ 'import portage' to prevent unnecessary tracing
98 if debug and "python-trace" in portage.features:
100 portage.debug.set_trace(True)
102 if not opts.color == 'y' and \
103 (opts.color == 'n' or \
104 portage.settings.get('NOCOLOR') in ('yes', 'true') or \
105 portage.settings.get('TERM') == 'dumb' or \
106 not sys.stdout.isatty()):
107 portage.output.nocolor()
108 portage.settings.unlock()
109 portage.settings['NOCOLOR'] = 'true'
110 portage.settings.lock()
112 ebuild = pargs.pop(0)
115 if ebuild.endswith(".ebuild"):
116 pf = os.path.basename(ebuild)[:-7]
119 portage.writemsg("'%s' does not end with '.ebuild'.\n" % \
120 (ebuild,), noiselevel=-1)
123 if not os.path.isabs(ebuild):
125 # Try to get the non-canonical path from the PWD evironment variable, since
126 # the canonical path returned from os.getcwd() may may be unusable in
127 # cases where the directory stucture is built from symlinks.
128 pwd = os.environ.get('PWD', '')
129 if sys.hexversion < 0x3000000:
130 pwd = _unicode_decode(pwd, encoding=_encodings['content'],
132 if pwd and pwd != mycwd and \
133 os.path.realpath(pwd) == mycwd:
134 mycwd = portage.normalize_path(pwd)
135 ebuild = os.path.join(mycwd, ebuild)
136 ebuild = portage.normalize_path(ebuild)
137 # portdbapi uses the canonical path for the base of the portage tree, but
138 # subdirectories of the base can be built from symlinks (like crossdev does).
139 ebuild_portdir = os.path.realpath(
140 os.path.dirname(os.path.dirname(os.path.dirname(ebuild))))
141 ebuild = os.path.join(ebuild_portdir, *ebuild.split(os.path.sep)[-3:])
142 vdb_path = os.path.realpath(os.path.join(portage.settings['EROOT'], VDB_PATH))
144 # Make sure that portdb.findname() returns the correct ebuild.
145 if ebuild_portdir != vdb_path and \
146 ebuild_portdir not in portage.portdb.porttrees:
147 portdir_overlay = portage.settings.get("PORTDIR_OVERLAY", "")
148 if sys.hexversion >= 0x3000000:
149 os.environ["PORTDIR_OVERLAY"] = \
151 " " + _shell_quote(ebuild_portdir)
153 os.environ["PORTDIR_OVERLAY"] = \
154 _unicode_encode(portdir_overlay,
155 encoding=_encodings['content'], errors='strict') + \
156 " " + _unicode_encode(_shell_quote(ebuild_portdir),
157 encoding=_encodings['content'], errors='strict')
159 print("Appending %s to PORTDIR_OVERLAY..." % ebuild_portdir)
163 if ebuild_portdir != vdb_path:
164 myrepo = portage.portdb.getRepositoryName(ebuild_portdir)
166 if not os.path.exists(ebuild):
167 print("'%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 print("!!! %s does not follow correct package syntax." % (cpv))
182 if ebuild.startswith(vdb_path):
184 pkg_type = "installed"
186 portage_ebuild = portage.db[portage.root][mytree].dbapi.findname(cpv, myrepo=myrepo)
188 if os.path.realpath(portage_ebuild) != ebuild:
189 print("!!! Portage seems to think that %s is at %s" % (cpv, portage_ebuild))
196 portage_ebuild = portage.portdb.findname(cpv, myrepo=myrepo)
198 if not portage_ebuild or portage_ebuild != ebuild:
199 print("!!! %s does not seem to have a valid PORTDIR structure." % ebuild)
202 if len(pargs) > 1 and "config" in pargs:
203 print("config must be called on it's own, not combined with any other phase")
206 def discard_digests(myebuild, mysettings, mydbapi):
207 """Discard all distfiles digests for the given ebuild. This is useful when
208 upstream has changed the identity of the distfiles and the user would
209 otherwise have to manually remove the Manifest and files/digest-* files in
210 order to ensure correct results."""
212 portage._doebuild_manifest_exempt_depend += 1
213 pkgdir = os.path.dirname(myebuild)
214 fetchlist_dict = portage.FetchlistDict(pkgdir, mysettings, mydbapi)
215 mf = mysettings.repositories.get_repo_for_location(
216 os.path.dirname(os.path.dirname(pkgdir)))
217 mf = mf.load_manifest(pkgdir, mysettings["DISTDIR"],
218 fetchlist_dict=fetchlist_dict)
219 mf.create(requiredDistfiles=None,
220 assumeDistHashesSometimes=True, assumeDistHashesAlways=True)
221 distfiles = fetchlist_dict[cpv]
222 for myfile in distfiles:
224 del mf.fhashdict["DIST"][myfile]
229 portage._doebuild_manifest_exempt_depend -= 1
231 portage.settings.validate() # generate warning messages if necessary
233 build_dir_phases = set(["setup", "unpack", "prepare", "configure", "compile",
234 "test", "install", "package", "rpm", "merge", "qmerge"])
236 # If the current metadata is invalid then force the ebuild to be
237 # sourced again even if $T/environment already exists.
238 ebuild_changed = False
239 if mytree == "porttree" and build_dir_phases.intersection(pargs):
241 portage.portdb._pull_valid_cache(cpv, ebuild, ebuild_portdir)[0] is None
243 tmpsettings = portage.config(clone=portage.settings)
244 tmpsettings["PORTAGE_VERBOSE"] = "1"
245 tmpsettings.backup_changes("PORTAGE_VERBOSE")
247 if opts.skip_manifest:
248 tmpsettings["EBUILD_SKIP_MANIFEST"] = "1"
249 tmpsettings.backup_changes("EBUILD_SKIP_MANIFEST")
251 if opts.skip_manifest or \
252 "digest" in tmpsettings.features or \
253 "digest" in pargs or \
255 portage._doebuild_manifest_exempt_depend += 1
258 # This variable is a signal to config.regenerate() to
259 # indicate that the test phase should be enabled regardless
260 # of problems such as masked "test" USE flag.
261 tmpsettings["EBUILD_FORCE_TEST"] = "1"
262 tmpsettings.backup_changes("EBUILD_FORCE_TEST")
263 tmpsettings.features.add("test")
265 tmpsettings.features.discard("fail-clean")
267 if "merge" in pargs and "noauto" in tmpsettings.features:
268 print("Disabling noauto in features... merge disables it. (qmerge doesn't)")
269 tmpsettings.features.discard("noauto")
272 metadata = dict(zip(Package.metadata_keys,
273 portage.db[portage.settings['EROOT']][mytree].dbapi.aux_get(
274 cpv, Package.metadata_keys, myrepo=myrepo)))
276 # aux_get failure, message should have been shown on stderr.
279 root_config = RootConfig(portage.settings,
280 portage.db[portage.settings['EROOT']], None)
282 pkg = Package(built=(pkg_type != "ebuild"), cpv=cpv,
283 installed=(pkg_type=="installed"),
284 metadata=metadata, root_config=root_config,
287 # Apply package.env and repo-level settings. This allows per-package
288 # FEATURES and other variables (possibly PORTAGE_TMPDIR) to be
289 # available as soon as possible. Also, note that the only way to ensure
290 # that setcpv gets metadata from the correct repository is to pass in
291 # a Package instance, as we do here (previously we had to modify
292 # portdb.porttrees in order to accomplish this).
293 tmpsettings.setcpv(pkg)
295 def stale_env_warning():
296 if "clean" not in pargs and \
297 "noauto" not in tmpsettings.features and \
298 build_dir_phases.intersection(pargs):
299 portage.doebuild_environment(ebuild, "setup", portage.root,
300 tmpsettings, debug, 1, portage.portdb)
301 env_filename = os.path.join(tmpsettings["T"], "environment")
302 if os.path.exists(env_filename):
303 msg = ("Existing ${T}/environment for '%s' will be sourced. " + \
304 "Run 'clean' to start with a fresh environment.") % \
305 (tmpsettings["PF"], )
306 from textwrap import wrap
309 portage.writemsg(">>> %s\n" % x)
312 open(os.path.join(tmpsettings['PORTAGE_BUILDDIR'],
313 '.ebuild_changed'), 'w')
315 from portage.exception import PermissionDenied, \
316 PortagePackageException, UnsupportedAPIException
318 if 'digest' in tmpsettings.features and \
319 not set(["digest", "manifest"]).intersection(pargs):
320 pargs = ['digest'] + pargs
322 checked_for_stale_env = False
326 if not checked_for_stale_env and arg not in ("digest","manifest"):
327 # This has to go after manifest generation since otherwise
328 # aux_get() might fail due to invalid ebuild digests.
330 checked_for_stale_env = True
332 if arg in ("digest", "manifest") and force:
333 discard_digests(ebuild, tmpsettings, portage.portdb)
334 a = portage.doebuild(ebuild, arg, portage.root, tmpsettings,
335 debug=debug, tree=mytree,
336 vartree=portage.db[portage.root]['vartree'])
337 except KeyboardInterrupt:
338 print("Interrupted.")
343 except UnsupportedAPIException as e:
344 from textwrap import wrap
345 msg = wrap(str(e), 70)
348 portage.writemsg("!!! %s\n" % x, noiselevel=-1)
350 except PortagePackageException as e:
351 portage.writemsg("!!! %s\n" % (e,), noiselevel=-1)
353 except PermissionDenied as e:
354 portage.writemsg("!!! Permission Denied: %s\n" % (e,), noiselevel=-1)
357 print("Could not run the required binary?")