1 # Copyright 1999-2009 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
5 from _emerge.EbuildExecuter import EbuildExecuter
6 from _emerge.EbuildPhase import EbuildPhase
7 from _emerge.EbuildBinpkg import EbuildBinpkg
8 from _emerge.EbuildFetcher import EbuildFetcher
9 from _emerge.CompositeTask import CompositeTask
10 from _emerge.EbuildMerge import EbuildMerge
11 from _emerge.EbuildFetchonly import EbuildFetchonly
12 from _emerge.EbuildBuildDir import EbuildBuildDir
13 from portage.util import writemsg
15 from portage import os
16 from portage import _encodings
17 from portage import _unicode_encode
19 from portage.output import colorize
20 class EbuildBuild(CompositeTask):
22 __slots__ = ("args_set", "config_pool", "find_blockers",
23 "ldpath_mtimes", "logger", "opts", "pkg", "pkg_count",
24 "prefetcher", "settings", "world_atom") + \
25 ("_build_dir", "_buildpkg", "_ebuild_path", "_issyspkg", "_tree")
32 settings = self.settings
33 world_atom = self.world_atom
34 root_config = pkg.root_config
37 portdb = root_config.trees[tree].dbapi
39 settings.configdict["pkg"]["EMERGE_FROM"] = pkg.type_name
40 ebuild_path = portdb.findname(pkg.cpv)
41 if ebuild_path is None:
42 raise AssertionError("ebuild not found for '%s'" % pkg.cpv)
43 self._ebuild_path = ebuild_path
45 prefetcher = self.prefetcher
46 if prefetcher is None:
48 elif not prefetcher.isAlive():
50 elif prefetcher.poll() is None:
52 waiting_msg = "Fetching files " + \
53 "in the background. " + \
54 "To view fetch progress, run `tail -f " + \
55 "/var/log/emerge-fetch.log` in another " + \
57 msg_prefix = colorize("GOOD", " * ")
58 from textwrap import wrap
59 waiting_msg = "".join("%s%s\n" % (msg_prefix, line) \
60 for line in wrap(waiting_msg, 65))
61 if not self.background:
62 writemsg(waiting_msg, noiselevel=-1)
64 self._current_task = prefetcher
65 prefetcher.addExitListener(self._prefetch_exit)
68 self._prefetch_exit(prefetcher)
70 def _prefetch_exit(self, prefetcher):
74 settings = self.settings
77 fetcher = EbuildFetchonly(
78 fetch_all=opts.fetch_all_uri,
79 pkg=pkg, pretend=opts.pretend,
81 retval = fetcher.execute()
82 self.returncode = retval
86 fetcher = EbuildFetcher(config_pool=self.config_pool,
87 fetchall=opts.fetch_all_uri,
88 fetchonly=opts.fetchonly,
89 background=self.background,
90 pkg=pkg, scheduler=self.scheduler)
92 self._start_task(fetcher, self._fetch_exit)
94 def _fetch_exit(self, fetcher):
100 fetch_failed = self._final_exit(fetcher) != os.EX_OK
102 fetch_failed = self._default_exit(fetcher) != os.EX_OK
104 if fetch_failed and fetcher.logfile is not None and \
105 os.path.exists(fetcher.logfile):
106 self.settings["PORTAGE_LOG_FILE"] = fetcher.logfile
108 if not fetch_failed and fetcher.logfile is not None:
109 # Fetch was successful, so remove the fetch log.
111 os.unlink(fetcher.logfile)
115 if fetch_failed or opts.fetchonly:
121 pkg_count = self.pkg_count
122 scheduler = self.scheduler
123 settings = self.settings
124 features = settings.features
125 ebuild_path = self._ebuild_path
126 system_set = pkg.root_config.sets["system"]
128 self._build_dir = EbuildBuildDir(pkg=pkg, settings=settings)
129 self._build_dir.lock()
131 # Cleaning is triggered before the setup
132 # phase, in portage.doebuild().
133 msg = " === (%s of %s) Cleaning (%s::%s)" % \
134 (pkg_count.curval, pkg_count.maxval, pkg.cpv, ebuild_path)
135 short_msg = "emerge: (%s of %s) %s Clean" % \
136 (pkg_count.curval, pkg_count.maxval, pkg.cpv)
137 logger.log(msg, short_msg=short_msg)
139 #buildsyspkg: Check if we need to _force_ binary package creation
140 self._issyspkg = "buildsyspkg" in features and \
141 system_set.findAtomForPackage(pkg) and \
144 if opts.buildpkg or self._issyspkg:
146 self._buildpkg = True
148 msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
149 (pkg_count.curval, pkg_count.maxval, pkg.cpv, ebuild_path)
150 short_msg = "emerge: (%s of %s) %s Compile" % \
151 (pkg_count.curval, pkg_count.maxval, pkg.cpv)
152 logger.log(msg, short_msg=short_msg)
155 msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
156 (pkg_count.curval, pkg_count.maxval, pkg.cpv, ebuild_path)
157 short_msg = "emerge: (%s of %s) %s Compile" % \
158 (pkg_count.curval, pkg_count.maxval, pkg.cpv)
159 logger.log(msg, short_msg=short_msg)
161 build = EbuildExecuter(background=self.background, pkg=pkg,
162 scheduler=scheduler, settings=settings)
163 self._start_task(build, self._build_exit)
165 def _unlock_builddir(self):
166 portage.elog.elog_process(self.pkg.cpv, self.settings)
167 self._build_dir.unlock()
169 def _build_exit(self, build):
170 if self._default_exit(build) != os.EX_OK:
171 self._unlock_builddir()
176 buildpkg = self._buildpkg
179 self._final_exit(build)
184 msg = ">>> This is a system package, " + \
185 "let's pack a rescue tarball.\n"
187 log_path = self.settings.get("PORTAGE_LOG_FILE")
188 if log_path is not None:
189 log_file = codecs.open(_unicode_encode(log_path,
190 encoding=_encodings['fs'], errors='strict'),
191 mode='a', encoding=_encodings['content'], errors='replace')
197 if not self.background:
198 portage.writemsg_stdout(msg, noiselevel=-1)
200 packager = EbuildBinpkg(background=self.background, pkg=self.pkg,
201 scheduler=self.scheduler, settings=self.settings)
203 self._start_task(packager, self._buildpkg_exit)
205 def _buildpkg_exit(self, packager):
207 Released build dir lock when there is a failure or
208 when in buildpkgonly mode. Otherwise, the lock will
209 be released when merge() is called.
212 if self._default_exit(packager) != os.EX_OK:
213 self._unlock_builddir()
217 if self.opts.buildpkgonly:
218 # Need to call "clean" phase for buildpkgonly mode
219 portage.elog.elog_process(self.pkg.cpv, self.settings)
221 clean_phase = EbuildPhase(background=self.background,
222 pkg=self.pkg, phase=phase,
223 scheduler=self.scheduler, settings=self.settings,
225 self._start_task(clean_phase, self._clean_exit)
228 # Continue holding the builddir lock until
229 # after the package has been installed.
230 self._current_task = None
231 self.returncode = packager.returncode
234 def _clean_exit(self, clean_phase):
235 if self._final_exit(clean_phase) != os.EX_OK or \
236 self.opts.buildpkgonly:
237 self._unlock_builddir()
242 Install the package and then clean up and release locks.
243 Only call this after the build has completed successfully
244 and neither fetchonly nor buildpkgonly mode are enabled.
247 find_blockers = self.find_blockers
248 ldpath_mtimes = self.ldpath_mtimes
251 pkg_count = self.pkg_count
252 settings = self.settings
253 world_atom = self.world_atom
254 ebuild_path = self._ebuild_path
257 merge = EbuildMerge(find_blockers=self.find_blockers,
258 ldpath_mtimes=ldpath_mtimes, logger=logger, pkg=pkg,
259 pkg_count=pkg_count, pkg_path=ebuild_path,
260 scheduler=self.scheduler,
261 settings=settings, tree=tree, world_atom=world_atom)
263 msg = " === (%s of %s) Merging (%s::%s)" % \
264 (pkg_count.curval, pkg_count.maxval,
265 pkg.cpv, ebuild_path)
266 short_msg = "emerge: (%s of %s) %s Merge" % \
267 (pkg_count.curval, pkg_count.maxval, pkg.cpv)
268 logger.log(msg, short_msg=short_msg)
271 rval = merge.execute()
273 self._unlock_builddir()