Traverses the dependency graph of 'target' and return all targets that will
        be created before this one is created. If root of some dependency graph is
        found during traversal, it's either included or not, dependencing of the
        value of 'include_roots'. In either case, sources of root are not traversed.

def traverse (target, include_roots = False, include_sources = False):
    """ Traverses the dependency graph of 'target' and return all targets that will
        be created before this one is created. If root of some dependency graph is
        found during traversal, it's either included or not, dependencing of the
        value of 'include_roots'. In either case, sources of root are not traversed.
    """
    assert isinstance(target, VirtualTarget)
    assert isinstance(include_roots, (int, bool))
    assert isinstance(include_sources, (int, bool))
    result = []

    if target.action ():
        action = target.action ()

        # This includes 'target' as well
        result += action.targets ()

        for t in action.sources ():

            # FIXME:
            # TODO: see comment in Manager.register_object ()
            #if not isinstance (t, VirtualTarget):
            #    t = target.project_.manager_.get_object (t)

            if not t.root ():
                result += traverse (t, include_roots, include_sources)

            elif include_roots:
                result.append (t)

    elif include_sources:
        result.append (target)

    return result