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['ROOT'], 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()
152 del portage.portdb.porttrees[1:]
153 if ebuild_portdir != portage.portdb.porttree_root:
154 portage.portdb.porttrees.append(ebuild_portdir)
156 if not os.path.exists(ebuild):
157 print("'%s' does not exist." % ebuild)
160 ebuild_split = ebuild.split("/")
161 cpv = "%s/%s" % (ebuild_split[-3], pf)
163 if not portage.catpkgsplit(cpv):
164 print("!!! %s does not follow correct package syntax." % (cpv))
167 if ebuild.startswith(os.path.join(portage.root, portage.const.VDB_PATH)):
170 portage_ebuild = portage.db[portage.root][mytree].dbapi.findname(cpv)
172 if os.path.realpath(portage_ebuild) != ebuild:
173 print("!!! Portage seems to think that %s is at %s" % (cpv, portage_ebuild))
179 portage_ebuild = portage.portdb.findname(cpv)
181 if not portage_ebuild or portage_ebuild != ebuild:
182 print("!!! %s does not seem to have a valid PORTDIR structure." % ebuild)
185 if len(pargs) > 1 and "config" in pargs:
186 print("config must be called on it's own, not combined with any other phase")
189 def discard_digests(myebuild, mysettings, mydbapi):
190 """Discard all distfiles digests for the given ebuild. This is useful when
191 upstream has changed the identity of the distfiles and the user would
192 otherwise have to manually remove the Manifest and files/digest-* files in
193 order to ensure correct results."""
195 portage._doebuild_manifest_exempt_depend += 1
196 pkgdir = os.path.dirname(myebuild)
197 fetchlist_dict = portage.FetchlistDict(pkgdir, mysettings, mydbapi)
198 from portage.manifest import Manifest
199 mf = Manifest(pkgdir, mysettings["DISTDIR"],
200 fetchlist_dict=fetchlist_dict, manifest1_compat=False)
201 mf.create(requiredDistfiles=None,
202 assumeDistHashesSometimes=True, assumeDistHashesAlways=True)
203 distfiles = fetchlist_dict[cpv]
204 for myfile in distfiles:
206 del mf.fhashdict["DIST"][myfile]
211 portage._doebuild_manifest_exempt_depend -= 1
213 portage.settings.validate() # generate warning messages if necessary
214 tmpsettings = portage.config(clone=portage.settings)
215 tmpsettings["PORTAGE_VERBOSE"] = "1"
216 tmpsettings.backup_changes("PORTAGE_VERBOSE")
218 # This variable is a signal to config.regenerate() to
219 # indicate that the test phase should be enabled regardless
220 # of problems such as masked "test" USE flag.
221 tmpsettings["EBUILD_FORCE_TEST"] = "1"
222 tmpsettings.backup_changes("EBUILD_FORCE_TEST")
223 tmpsettings.features.add("test")
225 tmpsettings.features.discard('fail-clean')
227 if opts.skip_manifest:
228 tmpsettings["EBUILD_SKIP_MANIFEST"] = "1"
229 tmpsettings.backup_changes("EBUILD_SKIP_MANIFEST")
230 portage._doebuild_manifest_exempt_depend += 1
232 build_dir_phases = set(["setup", "unpack", "prepare", "configure", "compile",
233 "test", "install", "package", "rpm", "merge", "qmerge"])
235 # If the current metadata is invalid then force the ebuild to be
236 # sourced again even if $T/environment already exists.
237 ebuild_changed = False
238 if build_dir_phases.intersection(pargs):
239 metadata, st, emtime = \
240 portage.portdb._pull_valid_cache(cpv, ebuild, ebuild_portdir)
242 ebuild_changed = True
244 def stale_env_warning():
245 if "clean" not in pargs and \
246 "noauto" not in tmpsettings.features and \
247 build_dir_phases.intersection(pargs):
248 portage.doebuild_environment(ebuild, "setup", portage.root,
249 tmpsettings, debug, 1, portage.portdb)
250 env_filename = os.path.join(tmpsettings["T"], "environment")
251 if os.path.exists(env_filename):
252 msg = ("Existing ${T}/environment for '%s' will be sourced. " + \
253 "Run 'clean' to start with a fresh environment.") % \
254 (tmpsettings["PF"], )
255 from textwrap import wrap
258 portage.writemsg(">>> %s\n" % x)
261 open(os.path.join(tmpsettings['PORTAGE_BUILDDIR'],
262 '.ebuild_changed'), 'w')
264 from portage.exception import PermissionDenied, \
265 PortagePackageException, UnsupportedAPIException
267 if 'digest' in tmpsettings.features and \
268 not set(["digest", "manifest"]).intersection(pargs):
269 pargs = ['digest'] + pargs
271 checked_for_stale_env = False
275 if not checked_for_stale_env and arg not in ("digest","manifest"):
276 # This has to go after manifest generation since otherwise
277 # aux_get() might fail due to invalid ebuild digests.
279 checked_for_stale_env = True
281 if arg in ("digest", "manifest") and force:
282 discard_digests(ebuild, tmpsettings, portage.portdb)
283 a = portage.doebuild(ebuild, arg, portage.root, tmpsettings,
284 debug=debug, tree=mytree,
285 vartree=portage.db[portage.root]['vartree'])
286 except KeyboardInterrupt:
287 print("Interrupted.")
292 except UnsupportedAPIException as e:
293 from textwrap import wrap
294 msg = wrap(str(e), 70)
297 portage.writemsg("!!! %s\n" % x, noiselevel=-1)
299 except PortagePackageException as e:
300 portage.writemsg("!!! %s\n" % (e,), noiselevel=-1)
302 except PermissionDenied as e:
303 portage.writemsg("!!! Permission Denied: %s\n" % (e,), noiselevel=-1)
306 print("Could not run the required binary?")