2 # Copyright 1999-2010 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 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.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
220 tmpsettings = portage.config(clone=portage.settings)
221 tmpsettings["PORTAGE_VERBOSE"] = "1"
222 tmpsettings.backup_changes("PORTAGE_VERBOSE")
224 # This variable is a signal to config.regenerate() to
225 # indicate that the test phase should be enabled regardless
226 # of problems such as masked "test" USE flag.
227 tmpsettings["EBUILD_FORCE_TEST"] = "1"
228 tmpsettings.backup_changes("EBUILD_FORCE_TEST")
229 tmpsettings.features.add("test")
231 tmpsettings.features.discard('fail-clean')
233 if opts.skip_manifest:
234 tmpsettings["EBUILD_SKIP_MANIFEST"] = "1"
235 tmpsettings.backup_changes("EBUILD_SKIP_MANIFEST")
236 portage._doebuild_manifest_exempt_depend += 1
238 build_dir_phases = set(["setup", "unpack", "prepare", "configure", "compile",
239 "test", "install", "package", "rpm", "merge", "qmerge"])
241 # If the current metadata is invalid then force the ebuild to be
242 # sourced again even if $T/environment already exists.
243 ebuild_changed = False
244 if build_dir_phases.intersection(pargs):
245 metadata, st, emtime = \
246 portage.portdb._pull_valid_cache(cpv, ebuild, ebuild_portdir)
248 ebuild_changed = True
250 def stale_env_warning():
251 if "clean" not in pargs and \
252 "noauto" not in tmpsettings.features and \
253 build_dir_phases.intersection(pargs):
254 portage.doebuild_environment(ebuild, "setup", portage.root,
255 tmpsettings, debug, 1, portage.portdb)
256 env_filename = os.path.join(tmpsettings["T"], "environment")
257 if os.path.exists(env_filename):
258 msg = ("Existing ${T}/environment for '%s' will be sourced. " + \
259 "Run 'clean' to start with a fresh environment.") % \
260 (tmpsettings["PF"], )
261 from textwrap import wrap
264 portage.writemsg(">>> %s\n" % x)
267 open(os.path.join(tmpsettings['PORTAGE_BUILDDIR'],
268 '.ebuild_changed'), 'w')
270 from portage.exception import PermissionDenied, \
271 PortagePackageException, UnsupportedAPIException
273 if 'digest' in tmpsettings.features and \
274 not set(["digest", "manifest"]).intersection(pargs):
275 pargs = ['digest'] + pargs
277 checked_for_stale_env = False
281 if not checked_for_stale_env and arg not in ("digest","manifest"):
282 # This has to go after manifest generation since otherwise
283 # aux_get() might fail due to invalid ebuild digests.
285 checked_for_stale_env = True
287 if arg in ("digest", "manifest") and force:
288 discard_digests(ebuild, tmpsettings, portage.portdb)
289 a = portage.doebuild(ebuild, arg, portage.root, tmpsettings,
290 debug=debug, tree=mytree,
291 vartree=portage.db[portage.root]['vartree'])
292 except KeyboardInterrupt:
293 print("Interrupted.")
298 except UnsupportedAPIException as e:
299 from textwrap import wrap
300 msg = wrap(str(e), 70)
303 portage.writemsg("!!! %s\n" % x, noiselevel=-1)
305 except PortagePackageException as e:
306 portage.writemsg("!!! %s\n" % (e,), noiselevel=-1)
308 except PermissionDenied as e:
309 portage.writemsg("!!! Permission Denied: %s\n" % (e,), noiselevel=-1)
312 print("Could not run the required binary?")