def _find_depender(dkey, blade):
    """Find which target depends on the target with dkey. """
    target_database = blade.get_target_database()
    for key in target_database:
        target = target_database[key]
        if dkey in target.expanded_deps:
            return '//%s' % target.fullname
    return None
def _find_depender(dkey, blade):
    """_find_depender to find which target depends on the target with dkey.

    """
    target_database = blade.get_target_database()
    for key in target_database:
        if dkey in target_database[key].expanded_deps:
            return "//%s:%s" % (target_database[key].path, target_database[key].name)
    return None
def _find_dir_depender(dir, blade):
    """Find which target depends on the dir. """
    target_database = blade.get_target_database()
    for key in target_database:
        target = target_database[key]
        for dkey in target.expanded_deps:
            if dkey[0] == dir:
                return '//%s' % target.fullname
    return None
def _find_dir_depender(dir, blade):
    """_find_dir_depender to find which target depends on the dir.

    """
    target_database = blade.get_target_database()
    for key in target_database:
        for dkey in target_database[key].expanded_deps:
            if dkey[0] == dir:
                return "//%s:%s" % (target_database[key].path, target_database[key].name)
    return None
def load_targets(target_ids, working_dir, blade_root_dir, blade):
    """load_targets.

    Parse and load targets, including those specified in command line
    and their direct and indirect dependencies, by loading related BUILD
    files.  Returns a map which contains all these targets.

    """
    target_database = blade.get_target_database()

    # targets specified in command line
    cited_targets = set()
    # cited_targets and all its dependencies
    related_targets = {}
    # source dirs mentioned in command line
    source_dirs = []
    # to prevent duplicated loading of BUILD files
    processed_source_dirs = set()

    direct_targets = []
    all_command_targets = []
    # Parse command line target_ids.  For those in the form of <path>:<target>,
    # record (<path>,<target>) in cited_targets; for the rest (with <path>
    # but without <target>), record <path> into paths.
    for target_id in target_ids:
        if target_id.find(":") == -1:
            source_dir, target_name = target_id, "*"
        else:
            source_dir, target_name = target_id.rsplit(":", 1)

        source_dir = relative_path(os.path.join(working_dir, source_dir), blade_root_dir)

        if target_name != "*" and target_name != "":
            cited_targets.add((source_dir, target_name))
        elif source_dir.endswith("..."):
            source_dir = source_dir[:-3]
            if not source_dir:
                source_dir = "./"
            source_dirs.append((source_dir, WARN_IF_FAIL))
            for root, dirs, files in os.walk(source_dir):
                # Note the dirs[:] = slice assignment; we are replacing the
                # elements in dirs (and not the list referred to by dirs) so
                # that os.walk() will not process deleted directories.
                dirs[:] = [d for d in dirs if not _is_load_excluded(d)]
                for d in dirs:
                    source_dirs.append((os.path.join(root, d), IGNORE_IF_FAIL))
        else:
            source_dirs.append((source_dir, ABORT_IF_FAIL))

    direct_targets = list(cited_targets)

    # Load BUILD files in paths, and add all loaded targets into
    # cited_targets.  Together with above step, we can ensure that all
    # targets mentioned in the command line are now in cited_targets.
    for source_dir, action_if_fail in source_dirs:
        _load_build_file(source_dir, action_if_fail, processed_source_dirs, blade)

    for key in target_database:
        cited_targets.add(key)
    all_command_targets = list(cited_targets)

    # Starting from targets specified in command line, breath-first
    # propagate to load BUILD files containing directly and indirectly
    # dependent targets.  All these targets form related_targets,
    # which is a subset of target_databased created by loading  BUILD files.
    while cited_targets:
        source_dir, target_name = cited_targets.pop()
        target_id = (source_dir, target_name)
        if target_id in related_targets:
            continue

        _load_build_file(source_dir, ABORT_IF_FAIL, processed_source_dirs, blade)

        if target_id not in target_database:
            console.error_exit(
                "%s: target //%s:%s does not exists" % (_find_depender(target_id, blade), source_dir, target_name)
            )

        related_targets[target_id] = target_database[target_id]
        for key in related_targets[target_id].expanded_deps:
            if key not in related_targets:
                cited_targets.add(key)

    # Iterating to get svn root dirs
    for path, name in related_targets:
        root_dir = path.split("/")[0].strip()
        if root_dir not in blade.svn_root_dirs and "#" not in root_dir:
            blade.svn_root_dirs.append(root_dir)

    return direct_targets, all_command_targets, related_targets
def load_targets(target_ids, blade_root_dir, blade):
    """load_targets.

    Parse and load targets, including those specified in command line
    and their direct and indirect dependencies, by loading related BUILD
    files.  Returns a map which contains all these targets.

    """
    build_rules.register_variable('build_target', build_attributes.attributes)
    target_database = blade.get_target_database()

    # targets specified in command line
    cited_targets = set()
    # cited_targets and all its dependencies
    related_targets = {}
    # source dirs mentioned in command line
    source_dirs = []
    # to prevent duplicated loading of BUILD files
    processed_source_dirs = set()

    direct_targets = []
    all_command_targets = []
    # Parse command line target_ids.  For those in the form of <path>:<target>,
    # record (<path>,<target>) in cited_targets; for the rest (with <path>
    # but without <target>), record <path> into paths.
    for target_id in target_ids:
        source_dir, target_name = target_id.rsplit(':', 1)

        if target_name != '*' and target_name != '...':
            cited_targets.add((source_dir, target_name))
        elif target_name == '...':
            for root, dirs, files in os.walk(source_dir):
                # Note the dirs[:] = slice assignment; we are replacing the
                # elements in dirs (and not the list referred to by dirs) so
                # that os.walk() will not process deleted directories.
                dirs[:] = [d for d in dirs if not _is_load_excluded(d)]
                if 'BUILD' in files:
                    source_dirs.append(root)
        else:
            source_dirs.append(source_dir)

    direct_targets = list(cited_targets)

    # Load BUILD files in paths, and add all loaded targets into
    # cited_targets.  Together with above step, we can ensure that all
    # targets mentioned in the command line are now in cited_targets.
    for source_dir in source_dirs:
        _load_build_file(source_dir, processed_source_dirs, blade)

    for key in target_database:
        cited_targets.add(key)
    all_command_targets = list(cited_targets)

    # Starting from targets specified in command line, breath-first
    # propagate to load BUILD files containing directly and indirectly
    # dependent targets.  All these targets form related_targets,
    # which is a subset of target_databased created by loading  BUILD files.
    while cited_targets:
        source_dir, target_name = cited_targets.pop()
        target_id = (source_dir, target_name)
        if target_id in related_targets:
            continue

        _load_build_file(source_dir, processed_source_dirs, blade)

        if target_id not in target_database:
            console.error_exit(
                '%s: target //%s:%s does not exist' %
                (_find_depender(target_id, blade), source_dir, target_name))

        related_targets[target_id] = target_database[target_id]
        for key in related_targets[target_id].expanded_deps:
            if key not in related_targets:
                cited_targets.add(key)

    # Iterating to get svn root dirs
    for path, name in related_targets:
        root_dir = path.split('/')[0].strip()
        if root_dir not in blade.svn_root_dirs and '#' not in root_dir:
            blade.svn_root_dirs.append(root_dir)

    return direct_targets, all_command_targets, related_targets