2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
5 from __future__ import print_function
8 # 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)
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:
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 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
78 if not opts.ignore_default_opts:
79 default_opts = portage.settings.get("EBUILD_DEFAULT_OPTS", "").split()
80 opts, pargs = parser.parse_args(default_opts + sys.argv[1:])
85 import portage.util, portage.const
87 portage.dep._dep_check_strict = True
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 'parse-eapi-glep-55' in portage.settings.features:
108 pf, eapi = portage._split_ebuild_name_glep55(
109 os.path.basename(ebuild))
110 elif ebuild.endswith(".ebuild"):
111 pf = os.path.basename(ebuild)[:-7]
114 portage.writemsg("'%s' does not end with '.ebuild'.\n" % \
115 (ebuild,), noiselevel=-1)
118 if not os.path.isabs(ebuild):
120 # Try to get the non-canonical path from the PWD evironment variable, since
121 # the canonical path returned from os.getcwd() may may be unusable in
122 # cases where the directory stucture is built from symlinks.
123 pwd = os.environ.get('PWD', '')
124 if sys.hexversion < 0x3000000:
125 pwd = _unicode_decode(pwd, encoding=_encodings['content'],
127 if pwd and pwd != mycwd and \
128 os.path.realpath(pwd) == mycwd:
129 mycwd = portage.normalize_path(pwd)
130 ebuild = os.path.join(mycwd, ebuild)
131 ebuild = portage.normalize_path(ebuild)
132 # portdbapi uses the canonical path for the base of the portage tree, but
133 # subdirectories of the base can be built from symlinks (like crossdev does).
134 ebuild_portdir = os.path.realpath(
135 os.path.dirname(os.path.dirname(os.path.dirname(ebuild))))
136 ebuild = os.path.join(ebuild_portdir, *ebuild.split(os.path.sep)[-3:])
138 # Make sure that portdb.findname() returns the correct ebuild.
139 if ebuild_portdir not in portage.portdb.porttrees:
140 if sys.hexversion >= 0x3000000:
141 os.environ["PORTDIR_OVERLAY"] = \
142 os.environ.get("PORTDIR_OVERLAY","") + \
143 " " + _shell_quote(ebuild_portdir)
145 os.environ["PORTDIR_OVERLAY"] = \
146 os.environ.get("PORTDIR_OVERLAY","") + \
147 " " + _unicode_encode(_shell_quote(ebuild_portdir),
148 encoding=_encodings['content'], errors='strict')
150 print("Appending %s to PORTDIR_OVERLAY..." % ebuild_portdir)
151 portage.close_portdbapi_caches()
153 del portage.portdb.porttrees[1:]
154 if ebuild_portdir != portage.portdb.porttree_root:
155 portage.portdb.porttrees.append(ebuild_portdir)
157 if not os.path.exists(ebuild):
158 print("'%s' does not exist." % ebuild)
161 ebuild_split = ebuild.split("/")
162 cpv = "%s/%s" % (ebuild_split[-3], pf)
164 if not portage.catpkgsplit(cpv):
165 print("!!! %s does not follow correct package syntax." % (cpv))
168 if ebuild.startswith(os.path.join(portage.root, portage.const.VDB_PATH)):
171 portage_ebuild = portage.db[portage.root][mytree].dbapi.findname(cpv)
173 if os.path.realpath(portage_ebuild) != ebuild:
174 print("!!! Portage seems to think that %s is at %s" % (cpv, portage_ebuild))
180 portage_ebuild = portage.portdb.findname(cpv)
182 if not portage_ebuild or portage_ebuild != ebuild:
183 print("!!! %s does not seem to have a valid PORTDIR structure." % ebuild)
186 if len(pargs) > 1 and "config" in pargs:
187 print("config must be called on it's own, not combined with any other phase")
190 def discard_digests(myebuild, mysettings, mydbapi):
191 """Discard all distfiles digests for the given ebuild. This is useful when
192 upstream has changed the identity of the distfiles and the user would
193 otherwise have to manually remove the Manifest and files/digest-* files in
194 order to ensure correct results."""
196 portage._doebuild_manifest_exempt_depend += 1
197 pkgdir = os.path.dirname(myebuild)
198 fetchlist_dict = portage.FetchlistDict(pkgdir, mysettings, mydbapi)
199 from portage.manifest import Manifest
200 mf = Manifest(pkgdir, mysettings["DISTDIR"],
201 fetchlist_dict=fetchlist_dict, manifest1_compat=False)
202 mf.create(requiredDistfiles=None,
203 assumeDistHashesSometimes=True, assumeDistHashesAlways=True)
204 distfiles = fetchlist_dict[cpv]
205 for myfile in distfiles:
207 del mf.fhashdict["DIST"][myfile]
212 portage._doebuild_manifest_exempt_depend -= 1
214 portage.settings.validate() # generate warning messages if necessary
215 tmpsettings = portage.config(clone=portage.settings)
216 tmpsettings["PORTAGE_VERBOSE"] = "1"
217 tmpsettings.backup_changes("PORTAGE_VERBOSE")
219 # This variable is a signal to config.regenerate() to
220 # indicate that the test phase should be enabled regardless
221 # of problems such as masked "test" USE flag.
222 tmpsettings["EBUILD_FORCE_TEST"] = "1"
223 tmpsettings.backup_changes("EBUILD_FORCE_TEST")
224 if "test" not in tmpsettings.features:
225 tmpsettings.features.add("test")
226 tmpsettings["FEATURES"] = " ".join(sorted(tmpsettings.features))
227 tmpsettings.backup_changes("FEATURES")
229 if 'fail-clean' in tmpsettings.features:
230 tmpsettings.features.remove('fail-clean')
231 tmpsettings["FEATURES"] = " ".join(sorted(tmpsettings.features))
232 tmpsettings.backup_changes("FEATURES")
234 if opts.skip_manifest:
235 tmpsettings["EBUILD_SKIP_MANIFEST"] = "1"
236 tmpsettings.backup_changes("EBUILD_SKIP_MANIFEST")
237 portage._doebuild_manifest_exempt_depend += 1
239 build_dir_phases = set(["setup", "unpack", "prepare", "configure", "compile",
240 "test", "install", "package", "rpm", "merge", "qmerge"])
242 # If the current metadata is invalid then force the ebuild to be
243 # sourced again even if $T/environment already exists.
244 ebuild_changed = False
245 if build_dir_phases.intersection(pargs):
246 metadata, st, emtime = \
247 portage.portdb._pull_valid_cache(cpv, ebuild, ebuild_portdir)
249 ebuild_changed = True
251 def stale_env_warning():
252 if "clean" not in pargs and \
253 "noauto" not in tmpsettings.features and \
254 build_dir_phases.intersection(pargs):
255 portage.doebuild_environment(ebuild, "setup", portage.root,
256 tmpsettings, debug, 1, portage.portdb)
257 env_filename = os.path.join(tmpsettings["T"], "environment")
258 if os.path.exists(env_filename):
259 msg = ("Existing ${T}/environment for '%s' will be sourced. " + \
260 "Run 'clean' to start with a fresh environment.") % \
261 (tmpsettings["PF"], )
262 from textwrap import wrap
265 portage.writemsg(">>> %s\n" % x)
268 open(os.path.join(tmpsettings['PORTAGE_BUILDDIR'],
269 '.ebuild_changed'), 'w')
271 from portage.exception import PermissionDenied, \
272 PortagePackageException, UnsupportedAPIException
273 checked_for_stale_env = False
277 if not checked_for_stale_env and arg not in ("digest","manifest"):
278 # This has to go after manifest generation since otherwise
279 # aux_get() might fail due to invalid ebuild digests.
281 checked_for_stale_env = True
283 if arg in ("digest", "manifest") and force:
284 discard_digests(ebuild, tmpsettings, portage.portdb)
285 a = portage.doebuild(ebuild, arg, portage.root, tmpsettings,
286 debug=debug, tree=mytree,
287 vartree=portage.db[portage.root]['vartree'])
288 except KeyboardInterrupt:
289 print("Interrupted.")
294 except UnsupportedAPIException as e:
295 from textwrap import wrap
296 msg = wrap(str(e), 70)
299 portage.writemsg("!!! %s\n" % x, noiselevel=-1)
301 except PortagePackageException as e:
302 portage.writemsg("!!! %s\n" % (e,), noiselevel=-1)
304 except PermissionDenied as e:
305 portage.writemsg("!!! Permission Denied: %s\n" % (e,), noiselevel=-1)
308 print("Could not run the required binary?")