Example #1
0
    def boil(self, external_nodes):
        """
        Resolve everything we got, propagate build information
        backwards across the edges.

        external_nodes is an iterable of repo nodes.
        """
        loop_count = 0

        while True:
            loop_count += 1
            if loop_count > 1000:
                raise self.InfiniteLoopError()

            something_changed = self.__do_enlarge()
            if something_changed:
                continue

            do_next_round = False

            directory_builders = []
            for b in self.iter_builders():
                if not isinstance(b, DirectoryBuilder):
                    continue
                directory_builders.append(b)
                b.recollect_dependency_info()
                if b.node_dependency_info_changed():
                    do_next_round = True
                    pass
                pass

            if do_next_round:
                self.__current_digraph = None
                continue

            if self.__current_digraph:
                break

            all_nodes = directory_builders + list(external_nodes)
            self.__current_digraph = DirectedGraph(
                nodes=all_nodes, edgefinder=EdgeFinder(nodes=all_nodes))

            for n in directory_builders:
                n.node_relate_managed_builders(digraph=self.__current_digraph)
                pass

            pass

        self.__current_digraph.edgefinder().raise_unresolved()
        pass
Example #2
0
    def test1(self):

        #         bad1
        #       /      \
        # root /        good       yields good
        #      \       /----
        #       \     /
        #         bad2

        root = Node(Node.BAD)
        bad1 = Node(Node.BAD)
        bad2 = Node(Node.BAD)
        good = Node(Node.GOOD)

        digraph = DirectedGraph(nodes=[root, bad1, bad2, good],
                                edges=[
                                    Edge(tail=root, head=bad1),
                                    Edge(tail=root, head=bad2),
                                    Edge(tail=bad1, head=good),
                                    Edge(tail=bad2, head=good)
                                ])

        self.failUnlessEqual(
            set([good]),
            algorithm.nearest_property(digraph=digraph,
                                       entrypoint=root,
                                       property=GoodProperty()))
        pass
Example #3
0
    def test7(self):

        #          bad
        #        /
        #       /
        #      /
        # root ----------- good1
        #      \           -----     yields good1, good2 (good1 is seen through good2,
        #       \         /          but is a direct successor of root)
        #        \       /
        #          good2
        #          -----

        root = Node(Node.BAD)
        bad = Node(Node.BAD)
        good1 = Node(Node.GOOD)
        good2 = Node(Node.GOOD)
        digraph = DirectedGraph(nodes=[root, bad, good1, good2],
                                edges=[
                                    Edge(root, bad),
                                    Edge(root, good1),
                                    Edge(root, good2),
                                    Edge(good2, good1)
                                ])
        self.failUnlessEqual(
            set([good1, good2]),
            algorithm.nearest_property(digraph=digraph,
                                       entrypoint=root,
                                       property=GoodProperty()))
        pass
Example #4
0
    def test6(self):

        #         bad
        #       /     \
        #      /       \
        # root           good2
        #      \         -----     yields good1, good2
        #       \
        #         good1
        #         -----

        root = Node(Node.BAD)
        bad = Node(Node.BAD)
        good1 = Node(Node.GOOD)
        good2 = Node(Node.GOOD)
        digraph = DirectedGraph(
            nodes=[root, bad, good1, good2],
            edges=[Edge(root, bad),
                   Edge(root, good1),
                   Edge(bad, good2)])
        self.failUnlessEqual(
            set([good1, good2]),
            algorithm.nearest_property(digraph=digraph,
                                       entrypoint=root,
                                       property=GoodProperty()))
        pass
Example #5
0
    def test3(self):

        #                 good1 --- good3
        #               / -----     -----
        #         bad1 /
        #       /      \             yields good1, good2
        # root /        \ good2
        #      \         /-----
        #       \       /
        #         bad2 /

        root = Node(Node.BAD)
        bad1 = Node(Node.BAD)
        bad2 = Node(Node.BAD)
        good1 = Node(Node.GOOD)
        good2 = Node(Node.GOOD)
        good3 = Node(Node.GOOD)
        digraph = DirectedGraph(nodes=[root, bad1, bad2, good1, good2, good3],
                                edges=[
                                    Edge(root, bad1),
                                    Edge(root, bad2),
                                    Edge(bad1, good1),
                                    Edge(bad1, good2),
                                    Edge(bad2, good2),
                                    Edge(good1, good3)
                                ])
        self.failUnlessEqual(
            set([good1, good2]),
            algorithm.nearest_property(digraph=digraph,
                                       entrypoint=root,
                                       property=GoodProperty()))
        pass
Example #6
0
    def test0(self):

        # root ---- bad      yields []

        root = Node(Node.BAD)
        bad = Node(Node.BAD)
        digraph = DirectedGraph(nodes=[root, bad], edges=[Edge(root, bad)])
        self.failUnlessEqual(
            set(),
            algorithm.nearest_property(digraph=digraph,
                                       entrypoint=root,
                                       property=GoodProperty()))
        pass
Example #7
0
    def test(self):
        n1 = object()
        n2 = object()
        n3 = object()
        n4 = object()

        g = algorithm.combine_graphs([DirectedGraph(nodes=[n1, n2, n3],
                                                    edges=[Edge(n1, n2),
                                                           Edge(n1, n3)]),
                                      DirectedGraph(nodes=[n2, n3],
                                                    edges=[Edge(n2, n3)]),
                                      DirectedGraph(nodes=[n3, n4],
                                                    edges=[Edge(n3, n4)]),
                                      DirectedGraph(nodes=[n1, n2],
                                                    edges=[Edge(n1, n2)])])
        self.failUnlessEqual(set([n1, n2, n3, n4]),
                             set(g.nodes()))

        self.failUnless(g.find_edge(n1, n2))
        self.failUnless(g.find_edge(n1, n3))
        self.failUnless(g.find_edge(n2, n3))
        self.failUnless(g.find_edge(n3, n4))
        pass
Example #8
0
    def test(self):
        n1 = object()
        n2 = object()
        n3 = object()

        digraph = DirectedGraph(nodes=[n1, n2, n3],
                                edges=[Edge(n1, n2),
                                       Edge(n1, n3)])
        self.failUnlessEqual(set([n1, n2, n3]),
                             set(algorithm.nodes_reached_from_including_entry(digraph, entrypoints=[n1])))

        digraph = DirectedGraph(nodes=[n1, n2, n3],
                                edges=[Edge(n1, n2),
                                       Edge(n2, n3)])
        self.failUnlessEqual(set([n1, n2, n3]),
                             set(algorithm.nodes_reached_from_including_entry(digraph, entrypoints=[n1])))

        digraph = DirectedGraph(nodes=[n1, n2, n3],
                                edges=[Edge(n1, n2),
                                       Edge(n2, n3)])
        self.failUnlessEqual(set([n2, n3]),
                             set(algorithm.nodes_reached_from_including_entry(digraph, entrypoints=[n2])))
        pass
Example #9
0
def main():
    try:
        nodes = []
        for filename in sys.argv[1:]:
            pkg = PackageFile(File(lines=lines_of_file(filename))).load()
            nodes.extend(pkg.nodes())
            pass

        graph = DirectedGraph(nodes=nodes, edgefinder=EdgeFinder(nodes=nodes))

        print '\n'.join(write_graph(graph))

    except Error, e:
        print ` e `
Example #10
0
    def test8(self):

        # root --- good1 --- good2     yields good1

        root = Node(Node.BAD)
        good1 = Node(Node.GOOD)
        good2 = Node(Node.GOOD)
        digraph = DirectedGraph(nodes=[root, good1, good2],
                                edges=[Edge(root, good1),
                                       Edge(good1, good2)])
        self.failUnlessEqual(
            set([good1]),
            algorithm.nearest_property(digraph=digraph,
                                       entrypoint=root,
                                       property=GoodProperty()))
        pass
Example #11
0
    def test(self):
        n1 = object()
        n2 = object()
        n3 = object()
        n4 = object()

        digraph = DirectedGraph(nodes=[n1, n2, n3, n4],
                                edges=[Edge(n1, n2),
                                       Edge(n2, n3),
                                       Edge(n3, n4),
                                       Edge(n1, n4)])
        subtracted_digraph = algorithm.subtract_nodes(digraph=digraph, nodes=[n2, n3])
        self.failUnlessEqual(set([n1, n4]),
                             set(subtracted_digraph.nodes()))
        self.failUnless(subtracted_digraph.find_edge(n1, n4))
        pass
Example #12
0
    def test2(self):

        #         bad
        #       /    \
        # root /______\ good    yields good
        #               ----

        root = Node(Node.BAD)
        bad = Node(Node.BAD)
        good = Node(Node.GOOD)

        digraph = DirectedGraph(
            nodes=[root, bad, good],
            edges=[Edge(root, bad),
                   Edge(root, good),
                   Edge(bad, good)])
        self.failUnlessEqual(
            set([good]),
            algorithm.nearest_property(digraph=digraph,
                                       entrypoint=root,
                                       property=GoodProperty()))
        pass
Example #13
0
class LocalPackage(Package):
    class InfiniteLoopError(Error):
        def __init__(self):
            Error.__init__(
                self,
                'Enlarge-loop entered for a ridiculously large number of times '
                '(some Builder must be misbehaving)')
            pass

        pass

    def __init__(self, rootdirectory, setups):
        self.__name = None
        self.__version = None
        self.__rootdirectory = rootdirectory

        self.__setup = None

        if setups:
            self.__set_setup(setups)
            pass

        self.__current_digraph = None

        # our directory builders, sorted topologically for output by
        # our backends.
        self.__topo_directories = None

        # read package definition file
        pkgdeffile = self.__rootdirectory.find([const.CONFIX2_PKG])
        if pkgdeffile is None:
            raise Error(const.CONFIX2_PKG + ' missing in ' +
                        os.sep.join(self.__rootdirectory.abspath()))
        InterfaceExecutor(iface_pieces=[PackageInterfaceProxy(
            package=self)]).execute_file(pkgdeffile)
        if self.__name is None:
            raise Error(const.CONFIX2_PKG + ': package name has not been set')
        if self.__version is None:
            raise Error(const.CONFIX2_PKG +
                        ': package version has not been set')

        if self.__setup is None:
            raise Error('No setup has been given; use SETUP() in Confix2.pkg')

        # create our root builder
        self.__rootbuilder = DirectoryBuilder(directory=rootdirectory)

        # now's the time to make everyone aware that we're no fun
        # anymore.
        self.__rootbuilder.initialize(package=self)

        pass

    def __str__(self):
        return 'LocalPackage:' + str(self.__name)

    def name(self):
        return self.__name

    def set_name(self, name):
        assert self.__name is None
        self.__name = name
        pass

    def version(self):
        return self.__version

    def set_version(self, version):
        assert self.__version is None
        self.__version = version
        pass

    def rootdirectory(self):
        return self.__rootdirectory

    def setup(self):
        return self.__setup

    def set_setup(self, s):
        self.__set_setup(s)
        pass

    def rootbuilder(self):
        return self.__rootbuilder

    def topo_directories(self):
        """
        Returns a toplogically sorted list of directory builder
        objects. Valid only during the output phase, once dependency
        calculation is complete.
        """
        assert self.__topo_directories is not None
        return self.__topo_directories

    def repofilename(self):
        """
        The name of the package's repo file.
        """
        return self.name() + '.repo'

    def digraph(self):
        return self.__current_digraph

    def boil(self, external_nodes):
        """
        Resolve everything we got, propagate build information
        backwards across the edges.

        external_nodes is an iterable of repo nodes.
        """
        loop_count = 0

        while True:
            loop_count += 1
            if loop_count > 1000:
                raise self.InfiniteLoopError()

            something_changed = self.__do_enlarge()
            if something_changed:
                continue

            do_next_round = False

            directory_builders = []
            for b in self.iter_builders():
                if not isinstance(b, DirectoryBuilder):
                    continue
                directory_builders.append(b)
                b.recollect_dependency_info()
                if b.node_dependency_info_changed():
                    do_next_round = True
                    pass
                pass

            if do_next_round:
                self.__current_digraph = None
                continue

            if self.__current_digraph:
                break

            all_nodes = directory_builders + list(external_nodes)
            self.__current_digraph = DirectedGraph(
                nodes=all_nodes, edgefinder=EdgeFinder(nodes=all_nodes))

            for n in directory_builders:
                n.node_relate_managed_builders(digraph=self.__current_digraph)
                pass

            pass

        self.__current_digraph.edgefinder().raise_unresolved()
        pass

    def output(self):
        self.__topo_directories = self.__sort_subdirs()

        # generate the package's repo file.
        repofilename = self.repofilename()
        repofile = self.__rootdirectory.find([repofilename])
        if repofile is None:
            repofile = self.__rootdirectory.add(name=repofilename,
                                                entry=File())
        else:
            repofile.truncate()
            pass

        PackageFile(file=repofile).dump(package=self.install())

        # recursively write the package's output
        self.__rootbuilder.output()

        pass

    def install(self):
        installed_nodes = []
        for b in self.iter_builders():
            if isinstance(b, DirectoryBuilder):
                installed_nodes.append(b.install())
                pass
            pass
        return InstalledPackage(name=self.name(),
                                version=self.version(),
                                nodes=installed_nodes)

    def iter_builders(self):
        """
        Returns an iterator over all builder objects that are
        maintained by this package. Use it when you do not intend to
        modify the set of builders when iterating.
        """
        yield self.__rootbuilder
        for builder in self.__rootbuilder.iter_builders_recursive():
            yield builder
            pass
        pass

    def __do_enlarge(self):
        """
        Enlarge our current set of builders by calling
        Builder.enlarge() on each.

        @return True if something has changed, False otherwise.
        """

        # copy them out because we will be changing the set once we
        # call enlarge on each builder.
        builders = [b for b in self.iter_builders()]

        prev_builder_props = {}
        for b in builders:
            prev_builder_props[b] = b.force_enlarge_count()
            pass

        for b in builders:
            try:
                b.enlarge()
            except Error as e:
                raise Error(
                    "Builder " + b.shortname() + " of " +
                    b.parentbuilder().shortname() + " encountered an error",
                    [e])
            pass

        for b in self.iter_builders():
            prev_enlarge_count = prev_builder_props.get(b)
            if prev_enlarge_count is None:
                # this is a new builder
                return True
            if prev_enlarge_count < b.force_enlarge_count():
                # b forced repetition
                return True
            pass

        return False

    def __sort_subdirs(self):
        # sort subdirectories topologically for our backends.
        subdir_nodes = set()
        for b in self.iter_builders():
            if isinstance(b, DirectoryBuilder):
                subdir_nodes.add(b)
                pass
            pass
        graph = algorithm.subgraph(digraph=self.__current_digraph,
                                   nodes=subdir_nodes)
        return toposort.toposort(digraph=graph, nodes=subdir_nodes)

    def __set_setup(self, s):
        assert self.__setup is None
        if isinstance(s, Setup):
            self.__setup = s
        elif type(s) in (list, tuple):
            self.__setup = CompositeSetup(s)
        else:
            assert False
            pass
        pass

    pass