2 # Copyright 1999-2011 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
5 from __future__ import print_function
9 # This block ensures that ^C interrupts are handled quietly.
12 def exithandler(signum,frame):
13 signal.signal(signal.SIGINT, signal.SIG_IGN)
14 signal.signal(signal.SIGTERM, signal.SIG_IGN)
15 sys.exit(128 + signum)
17 signal.signal(signal.SIGINT, exithandler)
18 signal.signal(signal.SIGTERM, exithandler)
19 # Prevent "[Errno 32] Broken pipe" exceptions when
21 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
23 except KeyboardInterrupt:
24 sys.exit(128 + signal.SIGINT)
26 def debug_signal(signum, frame):
29 signal.signal(signal.SIGUSR1, debug_signal)
35 description = "See the ebuild(1) man page for more info"
36 usage = "Usage: ebuild <ebuild file> <command> [command] ..."
37 parser = optparse.OptionParser(description=description, usage=usage)
39 force_help = "When used together with the digest or manifest " + \
40 "command, this option forces regeneration of digests for all " + \
41 "distfiles associated with the current ebuild. Any distfiles " + \
42 "that do not already exist in ${DISTDIR} will be automatically fetched."
44 parser.add_option("--force", help=force_help, action="store_true", dest="force")
45 parser.add_option("--color", help="enable or disable color output",
46 type="choice", choices=("y", "n"))
47 parser.add_option("--debug", help="show debug output",
48 action="store_true", dest="debug")
49 parser.add_option("--ignore-default-opts",
51 help="do not use the EBUILD_DEFAULT_OPTS environment variable")
52 parser.add_option("--skip-manifest", help="skip all manifest checks",
53 action="store_true", dest="skip_manifest")
55 opts, pargs = parser.parse_args(args=sys.argv[1:])
58 parser.error("missing required args")
61 print("Disabling noauto in features... merge disables it. (qmerge doesn't)")
62 os.environ["FEATURES"] = os.environ.get("FEATURES", "") + " -noauto"
64 os.environ["PORTAGE_CALLER"]="ebuild"
68 from os import path as osp
69 sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
72 portage.dep._internal_warnings = True
73 from portage import os
74 from portage import _encodings
75 from portage import _shell_quote
76 from portage import _unicode_decode
77 from portage import _unicode_encode
78 from portage.const import VDB_PATH
80 if not opts.ignore_default_opts:
81 default_opts = portage.settings.get("EBUILD_DEFAULT_OPTS", "").split()
82 opts, pargs = parser.parse_args(default_opts + sys.argv[1:])
87 import portage.util, portage.const
89 # do this _after_ 'import portage' to prevent unnecessary tracing
90 if debug and "python-trace" in portage.features:
92 portage.debug.set_trace(True)
94 if not opts.color == 'y' and \
95 (opts.color == 'n' or \
96 portage.settings.get('NOCOLOR') in ('yes', 'true') or \
97 portage.settings.get('TERM') == 'dumb' or \
98 not sys.stdout.isatty()):
99 portage.output.nocolor()
100 portage.settings.unlock()
101 portage.settings['NOCOLOR'] = 'true'
102 portage.settings.lock()
104 ebuild = pargs.pop(0)
107 if ebuild.endswith(".ebuild"):
108 pf = os.path.basename(ebuild)[:-7]
111 portage.writemsg("'%s' does not end with '.ebuild'.\n" % \
112 (ebuild,), noiselevel=-1)
115 if not os.path.isabs(ebuild):
117 # Try to get the non-canonical path from the PWD evironment variable, since
118 # the canonical path returned from os.getcwd() may may be unusable in
119 # cases where the directory stucture is built from symlinks.
120 pwd = os.environ.get('PWD', '')
121 if sys.hexversion < 0x3000000:
122 pwd = _unicode_decode(pwd, encoding=_encodings['content'],
124 if pwd and pwd != mycwd and \
125 os.path.realpath(pwd) == mycwd:
126 mycwd = portage.normalize_path(pwd)
127 ebuild = os.path.join(mycwd, ebuild)
128 ebuild = portage.normalize_path(ebuild)
129 # portdbapi uses the canonical path for the base of the portage tree, but
130 # subdirectories of the base can be built from symlinks (like crossdev does).
131 ebuild_portdir = os.path.realpath(
132 os.path.dirname(os.path.dirname(os.path.dirname(ebuild))))
133 ebuild = os.path.join(ebuild_portdir, *ebuild.split(os.path.sep)[-3:])
134 vdb_path = os.path.realpath(os.path.join(portage.settings['EROOT'], VDB_PATH))
136 # Make sure that portdb.findname() returns the correct ebuild.
137 if ebuild_portdir != vdb_path and \
138 ebuild_portdir not in portage.portdb.porttrees:
139 if sys.hexversion >= 0x3000000:
140 os.environ["PORTDIR_OVERLAY"] = \
141 os.environ.get("PORTDIR_OVERLAY","") + \
142 " " + _shell_quote(ebuild_portdir)
144 os.environ["PORTDIR_OVERLAY"] = \
145 os.environ.get("PORTDIR_OVERLAY","") + \
146 " " + _unicode_encode(_shell_quote(ebuild_portdir),
147 encoding=_encodings['content'], errors='strict')
149 print("Appending %s to PORTDIR_OVERLAY..." % ebuild_portdir)
150 portage.close_portdbapi_caches()
153 # Constrain eclass resolution to the master(s)
154 # that are specified in layout.conf (using an
155 # approach similar to repoman's).
157 if ebuild_portdir != vdb_path:
158 myrepo = portage.portdb.getRepositoryName(ebuild_portdir)
159 repo_info = portage.portdb._repo_info[ebuild_portdir]
160 portage.portdb.porttrees = list(repo_info.eclass_db.porttrees)
162 if not os.path.exists(ebuild):
163 print("'%s' does not exist." % ebuild)
166 ebuild_split = ebuild.split("/")
167 cpv = "%s/%s" % (ebuild_split[-3], pf)
169 if not portage.catpkgsplit(cpv):
170 print("!!! %s does not follow correct package syntax." % (cpv))
173 if ebuild.startswith(vdb_path):
176 portage_ebuild = portage.db[portage.root][mytree].dbapi.findname(cpv, myrepo=myrepo)
178 if os.path.realpath(portage_ebuild) != ebuild:
179 print("!!! Portage seems to think that %s is at %s" % (cpv, portage_ebuild))
185 portage_ebuild = portage.portdb.findname(cpv, myrepo=myrepo)
187 if not portage_ebuild or portage_ebuild != ebuild:
188 print("!!! %s does not seem to have a valid PORTDIR structure." % ebuild)
191 if len(pargs) > 1 and "config" in pargs:
192 print("config must be called on it's own, not combined with any other phase")
195 def discard_digests(myebuild, mysettings, mydbapi):
196 """Discard all distfiles digests for the given ebuild. This is useful when
197 upstream has changed the identity of the distfiles and the user would
198 otherwise have to manually remove the Manifest and files/digest-* files in
199 order to ensure correct results."""
201 portage._doebuild_manifest_exempt_depend += 1
202 pkgdir = os.path.dirname(myebuild)
203 fetchlist_dict = portage.FetchlistDict(pkgdir, mysettings, mydbapi)
204 from portage.manifest import Manifest
205 mf = Manifest(pkgdir, mysettings["DISTDIR"],
206 fetchlist_dict=fetchlist_dict, manifest1_compat=False)
207 mf.create(requiredDistfiles=None,
208 assumeDistHashesSometimes=True, assumeDistHashesAlways=True)
209 distfiles = fetchlist_dict[cpv]
210 for myfile in distfiles:
212 del mf.fhashdict["DIST"][myfile]
217 portage._doebuild_manifest_exempt_depend -= 1
219 portage.settings.validate() # generate warning messages if necessary
221 build_dir_phases = set(["setup", "unpack", "prepare", "configure", "compile",
222 "test", "install", "package", "rpm", "merge", "qmerge"])
224 # If the current metadata is invalid then force the ebuild to be
225 # sourced again even if $T/environment already exists.
226 ebuild_changed = False
227 if mytree == "porttree" and build_dir_phases.intersection(pargs):
228 metadata, st, emtime = \
229 portage.portdb._pull_valid_cache(cpv, ebuild, ebuild_portdir)
231 ebuild_changed = True
233 tmpsettings = portage.config(clone=portage.settings)
234 tmpsettings["PORTAGE_VERBOSE"] = "1"
235 tmpsettings.backup_changes("PORTAGE_VERBOSE")
237 if opts.skip_manifest:
238 tmpsettings["EBUILD_SKIP_MANIFEST"] = "1"
239 tmpsettings.backup_changes("EBUILD_SKIP_MANIFEST")
241 if opts.skip_manifest or \
242 "digest" in tmpsettings.features or \
243 "digest" in pargs or \
245 portage._doebuild_manifest_exempt_depend += 1
248 # This variable is a signal to config.regenerate() to
249 # indicate that the test phase should be enabled regardless
250 # of problems such as masked "test" USE flag.
251 tmpsettings["EBUILD_FORCE_TEST"] = "1"
252 tmpsettings.backup_changes("EBUILD_FORCE_TEST")
253 tmpsettings["FEATURES"] = tmpsettings.get("FEATURES", "") + " " + "test"
254 tmpsettings.backup_changes("FEATURES")
256 tmpsettings["FEATURES"] = tmpsettings.get("FEATURES", "") + " " + "-fail-clean"
257 tmpsettings.backup_changes("FEATURES")
259 # Apply package.env settings. This allows per-package FEATURES and other
260 # variables (possibly PORTAGE_TMPDIR) to be available as soon as possible.
262 tmpsettings.setcpv(cpv, mydb=portage.db[portage.root][mytree].dbapi)
264 # aux_get failure, message should have been shown on stderr.
267 def stale_env_warning():
268 if "clean" not in pargs and \
269 "noauto" not in tmpsettings.features and \
270 build_dir_phases.intersection(pargs):
271 portage.doebuild_environment(ebuild, "setup", portage.root,
272 tmpsettings, debug, 1, portage.portdb)
273 env_filename = os.path.join(tmpsettings["T"], "environment")
274 if os.path.exists(env_filename):
275 msg = ("Existing ${T}/environment for '%s' will be sourced. " + \
276 "Run 'clean' to start with a fresh environment.") % \
277 (tmpsettings["PF"], )
278 from textwrap import wrap
281 portage.writemsg(">>> %s\n" % x)
284 open(os.path.join(tmpsettings['PORTAGE_BUILDDIR'],
285 '.ebuild_changed'), 'w')
287 from portage.exception import PermissionDenied, \
288 PortagePackageException, UnsupportedAPIException
290 if 'digest' in tmpsettings.features and \
291 not set(["digest", "manifest"]).intersection(pargs):
292 pargs = ['digest'] + pargs
294 checked_for_stale_env = False
298 if not checked_for_stale_env and arg not in ("digest","manifest"):
299 # This has to go after manifest generation since otherwise
300 # aux_get() might fail due to invalid ebuild digests.
302 checked_for_stale_env = True
304 if arg in ("digest", "manifest") and force:
305 discard_digests(ebuild, tmpsettings, portage.portdb)
306 a = portage.doebuild(ebuild, arg, portage.root, tmpsettings,
307 debug=debug, tree=mytree,
308 vartree=portage.db[portage.root]['vartree'])
309 except KeyboardInterrupt:
310 print("Interrupted.")
315 except UnsupportedAPIException as e:
316 from textwrap import wrap
317 msg = wrap(str(e), 70)
320 portage.writemsg("!!! %s\n" % x, noiselevel=-1)
322 except PortagePackageException as e:
323 portage.writemsg("!!! %s\n" % (e,), noiselevel=-1)
325 except PermissionDenied as e:
326 portage.writemsg("!!! Permission Denied: %s\n" % (e,), noiselevel=-1)
329 print("Could not run the required binary?")