1 # Copyright 1999-2009 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
5 from _emerge.SpawnProcess import SpawnProcess
6 from _emerge.EbuildBuildDir import EbuildBuildDir
10 from portage import _encodings
11 from portage import _unicode_encode
13 from portage.elog.messages import eerror
15 class EbuildFetcher(SpawnProcess):
17 __slots__ = ("config_pool", "fetchonly", "fetchall", "pkg", "prefetch") + \
22 root_config = self.pkg.root_config
23 portdb = root_config.trees["porttree"].dbapi
24 ebuild_path = portdb.findname(self.pkg.cpv)
25 settings = self.config_pool.allocate()
26 settings.setcpv(self.pkg)
28 # In prefetch mode, logging goes to emerge-fetch.log and the builddir
29 # should not be touched since otherwise it could interfere with
30 # another instance of the same cpv concurrently being built for a
31 # different $ROOT (currently, builds only cooperate with prefetchers
32 # that are spawned for the same $ROOT).
34 self._build_dir = EbuildBuildDir(pkg=self.pkg, settings=settings)
35 self._build_dir.lock()
36 self._build_dir.clean_log()
37 portage.prepare_build_dirs(self.pkg.root, self._build_dir.settings, 0)
38 if self.logfile is None:
39 self.logfile = settings.get("PORTAGE_LOG_FILE")
45 # If any incremental variables have been overridden
46 # via the environment, those values need to be passed
47 # along here so that they are correctly considered by
48 # the config instance in the subproccess.
49 fetch_env = os.environ.copy()
51 nocolor = settings.get("NOCOLOR")
52 if nocolor is not None:
53 fetch_env["NOCOLOR"] = nocolor
55 fetch_env["PORTAGE_NICENESS"] = "0"
57 fetch_env["PORTAGE_PARALLEL_FETCHONLY"] = "1"
59 ebuild_binary = os.path.join(
60 settings["PORTAGE_BIN_PATH"], "ebuild")
62 fetch_args = [ebuild_binary, ebuild_path, phase]
63 debug = settings.get("PORTAGE_DEBUG") == "1"
65 fetch_args.append("--debug")
67 self.args = fetch_args
69 SpawnProcess._start(self)
71 def _pipe(self, fd_pipes):
72 """When appropriate, use a pty so that fetcher progress bars,
73 like wget has, will work properly."""
74 if self.background or not sys.stdout.isatty():
75 # When the output only goes to a log file,
76 # there's no point in creating a pty.
78 stdout_pipe = fd_pipes.get(1)
79 got_pty, master_fd, slave_fd = \
80 portage._create_pty_or_pipe(copy_term_size=stdout_pipe)
81 return (master_fd, slave_fd)
83 def _set_returncode(self, wait_retval):
84 SpawnProcess._set_returncode(self, wait_retval)
85 # Collect elog messages that might have been
86 # created by the pkg_nofetch phase.
87 if self._build_dir is not None:
88 # Skip elog messages for prefetch, in order to avoid duplicates.
89 if not self.prefetch and self.returncode != os.EX_OK:
91 if self.logfile is not None:
93 elog_out = codecs.open(_unicode_encode(self.logfile,
94 encoding=_encodings['fs'], errors='strict'),
95 mode='a', encoding=_encodings['content'], errors='replace')
96 msg = "Fetch failed for '%s'" % (self.pkg.cpv,)
97 if self.logfile is not None:
99 eerror(msg, phase="unpack", key=self.pkg.cpv, out=elog_out)
100 if self.logfile is not None:
101 eerror(" '%s'" % (self.logfile,),
102 phase="unpack", key=self.pkg.cpv, out=elog_out)
103 if elog_out is not None:
105 if not self.prefetch:
106 portage.elog.elog_process(self.pkg.cpv, self._build_dir.settings)
107 features = self._build_dir.settings.features
108 if self.returncode == os.EX_OK:
109 self._build_dir.clean_log()
110 self._build_dir.unlock()
111 self.config_pool.deallocate(self._build_dir.settings)
112 self._build_dir = None