示例#1
0
 def tests_get_cycles(self, pkg_source, expected):
     graph = PackageGraph("rawhide", pkg_source)
     graph.make_graph()
     assert graph.get_cycles() == expected
示例#2
0
class Builder(metaclass=ABCMeta):
    '''
    Abstract superclass of builder classes.
    '''

    def __init__(self, rebuild_metadata, pkg_source):
        self.pkg_source = pkg_source
        self.packages = set(rebuild_metadata['packages'])
        if 'metapackage' in rebuild_metadata:
            self.metapackage = rebuild_metadata['metapackage']
        self.repo = rebuild_metadata['repo']
        self.prefix = rebuild_metadata['prefix']
        self.koji_tag = rebuild_metadata['koji_tag']
        self.path = tempfile.mkdtemp()
        self.built_packages = set()
        self.num_of_deps = {}
        self.circular_deps = []
        self.get_files()
        self.graph = PackageGraph(self.repo, self.pkg_source)
        try:
            self.recipes = rebuild_metadata['recipes']
        except IOError:
            logger.error("Failed to load recipe {0}.".format(rebuild_metadata['recipes']))

    def __del__(self):
        shutil.rmtree(self.path)
        shutil.rmtree(self.__tempdir)

    @property
    def path(self):
        return self.__path

    @path.setter
    def path(self, value):
        self.__tempdir = value
        value += '/rebuild_tool-{0}/'.format(self.repo)
        if not os.path.isdir(value):
            os.makedirs(value)
        self.__path = value

    @property
    def recipes(self):
        return self.__recipes

    @recipes.setter
    def recipes(self, recipe_files):
        if not recipe_files:
            self.__recipes = None
        else:
            self.__recipes = [Recipe(recipe) for recipe in recipe_files]

    def get_relations(self):
        '''
        Runs graph analysis and get dependance tree and circular_deps
        '''
        self.graph.make_graph()
        self.circular_deps = self.graph.get_cycles()
        if self.circular_deps and not self.recipes:
            raise MissingRecipeException(
                "Missing recipes to resolve circular dependencies in graph.")

    def deps_satisfied(self, package):
        '''
        Compares package deps with self.build_packages to
        check if are all dependancies already built
        '''
        if set(self.graph.G.successors(package)) <= self.built_packages:
            return True
        return False

    def recipe_deps_satisfied(self, recipe):
        '''
        Checks if all packages in recipe have satisfied their
        dependencies on packages that are not in recipe
        '''
        deps = set()
        for pkg in recipe.packages:
            if not pkg in self.packages:
                raise KeyError("Package {} from recipe missing in packages list".format(pkg))
            deps |= set(self.graph.G.successors(pkg))

        if (deps - recipe.packages) <= self.built_packages:
            return True
        return False

    @check_build
    def build(self, pkgs, verbose=True):
        for pkg in pkgs:
            if verbose:
                print("Building {0}...".format(pkg))
        return True

    def run_building(self):
        '''
        First builds all packages without deps, then iterates over num_of_deps
        and simulate building of packages in right order
        '''

        # Build and add metapackage to chroots when rebuilding scl
        if hasattr(self, 'metapackage'):
            self.build([self.metapackage])
            self.add_chroot_pkg([self.metapackage])

        while self.packages > self.built_packages:
            zero_deps = self.graph.get_leaf_nodes()
            if zero_deps:
                self.build(zero_deps)
            else:
                for recipe in self.recipes:
                    if list(self.packages - self.built_packages)[1] in recipe.packages and\
                            self.recipe_deps_satisfied(recipe):
                        self.build_following_recipe(recipe)
                        break
                else:
                    sys.stderr.write("Recipe to resolve circular dependencies not found.\n")
                    raise SystemExit(1)

    def find_recipe(self, package):
        '''
        Search for recipe including package in self.recipes
        '''
        for recipe in self.recipes:
            if package in recipe.packages:
                return recipe
        raise MissingRecipeException("Recipe for package {0} not found".format(package))

    def build_following_recipe(self, recipe):
        '''
        Builds packages in order and macro values discribed in given
        recipe.
        '''
        for step in recipe.order:
            if len(step) == 1:
                print("Building package {0}".format(step[0]))
            else:
                (name, macro_value) = step
                print("Building package {0} {1}".format(name, macro_value))
                (macro, value) = macro_value.split(' ')
                utils.check_bootstrap_macro(self.pkg_source[name].full_path_spec, macro)
                utils.edit_bootstrap(self.pkg_source[name].full_path_spec, macro, value)
                self.pkg_source[name].pack()
            self.build([step[0]], False)
        for pkg in {step[0] for step in recipe.order}:
            self.graph.G.remove_node(pkg)
        self.recipes.remove(recipe)

    def get_files(self):
        '''
        Creates SrpmArchive object and downloads files for each package
        '''
        with utils.ChangeDir(self.path):
            for package in self.packages:
                pkg_dir = self.path + package + "_files/"
                if not os.path.exists(pkg_dir):
                    os.mkdir(pkg_dir)
                print("Getting files of {0}.".format(package))
                logger.debug("Getting files of {0}.".format(package))
                self.pkg_source.add(package, pkg_dir, self.repo, self.prefix, self.koji_tag)
示例#3
0
 def tests_get_cycles(self, pkg_source, expected):
     graph = PackageGraph("rawhide", pkg_source)
     graph.make_graph()
     assert graph.get_cycles() == expected