def fetch(self, target): """Fetch a file. :type target: :obj:`pkgcore.fetch.fetchable` instance :return: None if fetching failed, else on disk location of the copied file """ if not isinstance(target, fetchable): raise TypeError( f"target must be fetchable instance/derivative: {target}") path = pjoin(self.distdir, target.filename) uris = iter(target.uri) last_exc = RuntimeError("fetching failed for an unknown reason") spawn_opts = {'umask': 0o002, 'env': self.extra_env} if self.userpriv and is_userpriv_capable(): spawn_opts.update({"uid": portage_uid, "gid": portage_gid}) for _attempt in range(self.attempts): try: self._verify(path, target) return path except errors.MissingDistfile as e: command = self.command last_exc = e except errors.ChksumFailure: raise except errors.FetchFailed as e: last_exc = e if not e.resumable: try: os.unlink(path) command = self.command except OSError as e: raise errors.UnmodifiableFile(path, e) from e else: command = self.resume_command # Note we're not even checking the results, the verify portion of # the loop handles this. In other words, don't trust the external # fetcher's exit code, trust our chksums instead. try: spawn_bash( command % {"URI": next(uris), "FILE": target.filename}, **spawn_opts) except StopIteration: raise errors.FetchFailed( target.filename, "ran out of urls to fetch from") else: raise last_exc
def fetch(self, target): """ fetch a file :type target: :obj:`pkgcore.fetch.fetchable` instance :return: None if fetching failed, else on disk location of the copied file """ if not isinstance(target, fetchable): raise TypeError( "target must be fetchable instance/derivative: %s" % target) kw = {"mode": 0775} if self.readonly: kw["mode"] = 0555 if self.userpriv: kw["gid"] = portage_gid kw["minimal"] = True if not ensure_dirs(self.distdir, **kw): raise errors.distdirPerms( self.distdir, "if userpriv, uid must be %i, gid must be %i. " "if not readonly, directory must be 0775, else 0555" % (portage_uid, portage_gid)) fp = pjoin(self.distdir, target.filename) filename = os.path.basename(fp) uri = iter(target.uri) if self.userpriv and is_userpriv_capable(): extra = {"uid": portage_uid, "gid": portage_gid} else: extra = {} extra["umask"] = 0002 extra["env"] = self.extra_env attempts = self.attempts last_exc = None try: while attempts >= 0: try: c = self._verify(fp, target) return fp except errors.MissingDistfile: command = self.command last_exc = sys.exc_info() except errors.FetchFailed as e: last_exc = sys.exc_info() if not e.resumable: try: os.unlink(fp) command = self.command except OSError as oe: raise_from(errors.UnmodifiableFile(fp, oe)) else: command = self.resume_command # yeah, it's funky, but it works. if attempts > 0: u = uri.next() # note we're not even checking the results. the # verify portion of the loop handles this. iow, # don't trust their exit code. trust our chksums # instead. spawn_bash(command % {"URI": u, "FILE": filename}, **extra) attempts -= 1 assert last_exc is not None raise last_exc[0], last_exc[1], last_exc[2] except StopIteration: # ran out of uris raise errors.FetchFailed(fp, "Ran out of urls to fetch from")
try: cwd = os.getcwd() except OSError: cwd = "/" try: # crap. os.chmod(self.env["CCACHE_DIR"], 02775) os.chown(self.env["CCACHE_DIR"], -1, portage_gid) os.chdir(cwd) if 0 != spawn( ["chgrp", "-R", str(portage_gid), self.env["CCACHE_DIR"]]): raise format.FailedDirectory( self.env["CCACHE_DIR"], "failed changing ownership for CCACHE_DIR") if 0 != spawn_bash( "find '%s' -type d -print0 | %s --null chmod 02775" % (self.env["CCACHE_DIR"], xargs)): raise format.FailedDirectory( self.env["CCACHE_DIR"], "failed correcting perms for CCACHE_DIR") if 0 != spawn_bash( "find '%s' -type f -print0 | %s --null chmod 0775" % (self.env["CCACHE_DIR"], xargs)): raise format.FailedDirectory( self.env["CCACHE_DIR"], "failed correcting perms for CCACHE_DIR") finally: os.chdir(cwd) except OSError: raise_from(format.FailedDirectory(
def setup(self): """Execute the setup phase, mapping out to pkg_setup in the ebuild. Necessarily dirs are created as required, and build env is initialized at this point. """ if self.distcc: for p in ("", "/lock", "/state"): if not ensure_dirs(pjoin(self.env["DISTCC_DIR"], p), mode=0o2775, gid=portage_gid): raise format.FailedDirectory( pjoin(self.env["DISTCC_DIR"], p), "failed creating needed distcc directory") if self.ccache: # yuck. st = None try: st = os.stat(self.env["CCACHE_DIR"]) except OSError as e: st = None if not ensure_dirs(self.env["CCACHE_DIR"], mode=0o2775, gid=portage_gid): raise format.FailedDirectory( self.env["CCACHE_DIR"], "failed creation of ccache dir") from e # XXX this is more then mildly stupid. st = os.stat(self.env["CCACHE_DIR"]) try: if st.st_gid != portage_gid or (st.st_mode & 0o2775) != 0o2775: try: cwd = os.getcwd() except OSError: cwd = "/" with chdir(cwd): # crap. os.chmod(self.env["CCACHE_DIR"], 0o2775) os.chown(self.env["CCACHE_DIR"], -1, portage_gid) if 0 != spawn( ["chgrp", "-R", str(portage_gid), self.env["CCACHE_DIR"]]): raise format.FailedDirectory( self.env["CCACHE_DIR"], "failed changing ownership for CCACHE_DIR") if 0 != spawn_bash( "find '%s' -type d -print0 | %s --null chmod 02775" % (self.env["CCACHE_DIR"], xargs)): raise format.FailedDirectory( self.env["CCACHE_DIR"], "failed correcting perms for CCACHE_DIR") if 0 != spawn_bash( "find '%s' -type f -print0 | %s --null chmod 0775" % (self.env["CCACHE_DIR"], xargs)): raise format.FailedDirectory( self.env["CCACHE_DIR"], "failed correcting perms for CCACHE_DIR") except OSError as e: raise format.FailedDirectory( self.env["CCACHE_DIR"], "failed ensuring perms/group owner for CCACHE_DIR") from e return setup_mixin.setup(self)
def test_spawn_bash(self, capfd): # bash builtin for true without exec'ing true (eg, no path lookup) assert 0 == spawn.spawn_bash('echo bash') out, err = capfd.readouterr() assert out.strip() == 'bash'
def test_bash(self): # bash builtin for true without exec'ing true (eg, no path lookup) assert 0 == spawn.spawn_bash(":")
def fetch(self, target): """Fetch a file. :type target: :obj:`pkgcore.fetch.fetchable` instance :return: None if fetching failed, else on disk location of the copied file """ if not isinstance(target, fetchable): raise TypeError( f"target must be fetchable instance/derivative: {target}") kw = {"mode": 0o775} if self.readonly: kw["mode"] = 0o555 if self.userpriv: kw["gid"] = portage_gid kw["minimal"] = True if not ensure_dirs(self.distdir, **kw): raise errors.DistdirPerms( self.distdir, "if userpriv, uid must be %i, gid must be %i. " "if not readonly, directory must be 0775, else 0555" % ( portage_uid, portage_gid)) path = pjoin(self.distdir, target.filename) uris = iter(target.uri) last_exc = RuntimeError("fetching failed for an unknown reason") spawn_opts = {'umask': 0o002, 'env': self.extra_env} if self.userpriv and is_userpriv_capable(): spawn_opts.update({"uid": portage_uid, "gid": portage_gid}) for _attempt in range(self.attempts): try: self._verify(path, target) return path except errors.MissingDistfile as e: command = self.command last_exc = e except errors.ChksumFailure: raise except errors.FetchFailed as e: last_exc = e if not e.resumable: try: os.unlink(path) command = self.command except OSError as e: raise errors.UnmodifiableFile(path, e) from e else: command = self.resume_command # Note we're not even checking the results, the verify portion of # the loop handles this. In other words, don't trust the external # fetcher's exit code, trust our chksums instead. try: spawn_bash( command % {"URI": next(uris), "FILE": target.filename}, **spawn_opts) except StopIteration: raise errors.FetchFailed( target.filename, "ran out of urls to fetch from") else: raise last_exc