def is_bucket_available(self, bucket):
     """Check if bucket available on the platform"""
     all_in_cache = True
     for pkg_name in bucket:
         if pkg_name not in self.cache:
             # this can be also a foo:arch and we don't have <arch> added. Tell is may be available
             if ":" in pkg_name:
                 # /!\ danger: if current arch == ':appended_arch', on a non multiarch system, dpkg doesn't
                 # understand that. strip :arch then
                 (pkg_without_arch_name, arch) = pkg_name.split(":", -1)
                 if arch == get_current_arch() and pkg_without_arch_name in self.cache:  # false positive, available
                     continue
                 elif arch not in get_foreign_archs():  # relax the constraint
                     logger.info("{} isn't available on this platform, but {} isn't enabled. So it may be available "
                                 "later on".format(pkg_name, arch))
                     continue
             logger.info("{} isn't available on this platform".format(pkg_name))
             all_in_cache = False
     return all_in_cache
 def test_get_foreign_archs(self):
     """Get current foreign arch (multiple)"""
     with self.create_dpkg("echo fooarch\necho bararch\necho bazarch"):
         self.assertEquals(get_foreign_archs(), ["fooarch", "bararch", "bazarch"])
 def test_get_foreign_arch(self):
     """Get current foreign arch (one)"""
     with self.create_dpkg("echo fooarch"):
         self.assertEquals(get_foreign_archs(), ["fooarch"])
    def _really_install_bucket(self, current_bucket):
        """Really install current bucket and bind signals"""
        bucket = current_bucket["bucket"]
        logger.debug("Starting {} installation".format(bucket))

        # exchange file output for apt and dpkg after the fork() call (open it empty)
        self.apt_fd = tempfile.NamedTemporaryFile(delete=False)
        self.apt_fd.close()

        if self.is_bucket_uptodate(bucket):
            return True

        for pkg_name in bucket:
            if ":" in pkg_name:
                arch = pkg_name.split(":", -1)[-1]
                # try to add the arch
                if arch not in get_foreign_archs() and arch != get_current_arch():
                    logger.info("Adding foreign arch: {}".format(arch))
                    with open(os.devnull, "w") as f:
                        try:
                            os.seteuid(0)
                            os.setegid(0)
                            if subprocess.call(["dpkg", "--add-architecture", arch], stdout=f) != 0:
                                msg = "Can't add foreign foreign architecture {}".format(arch)
                                raise BaseException(msg)
                            self.cache.update()
                        finally:
                            switch_to_current_user()
                        self._force_reload_apt_cache()

        # mark for install and so on
        for pkg_name in bucket:
            # /!\ danger: if current arch == ':appended_arch', on a non multiarch system, dpkg doesn't understand that
            # strip :arch then
            if ":" in pkg_name:
                (pkg_without_arch_name, arch) = pkg_name.split(":", -1)
                if arch == get_current_arch():
                    pkg_name = pkg_without_arch_name
            try:
                pkg = self.cache[pkg_name]
                if pkg.is_installed and pkg.is_upgradable:
                    logger.debug("Marking {} for upgrade".format(pkg_name))
                    pkg.mark_upgrade()
                else:
                    logger.debug("Marking {} for install".format(pkg_name))
                    pkg.mark_install(auto_fix=False)
            except Exception as msg:
                message = "Can't mark for install {}: {}".format(pkg_name, msg)
                raise BaseException(message)

        # this can raise on installedArchives() exception if the commit() fails
        try:
            os.seteuid(0)
            os.setegid(0)
            self.cache.commit(fetch_progress=self._FetchProgress(current_bucket,
                                                                 self.STATUS_DOWNLOADING,
                                                                 current_bucket["progress_callback"]),
                              install_progress=self._InstallProgress(current_bucket,
                                                                     self.STATUS_INSTALLING,
                                                                     current_bucket["progress_callback"],
                                                                     self._force_reload_apt_cache,
                                                                     self.apt_fd.name))
        finally:
            switch_to_current_user()

        return True