fn get_dependencies()

in focus/internals/src/lib/index/content_hash.rs [217:332]


fn get_dependencies<'a>(
    ctx: &HashContext,
    dep_key: &'a DependencyKey,
) -> Result<(&'static str, Option<&'a Label>, Vec<KeyOrPath<'a>>)> {
    match dep_key {
        DependencyKey::BazelPackage(
            label @ Label {
                external_repository,
                path_components,
                target_name: _,
            },
        ) => {
            let path: PathBuf = path_components.iter().collect();
            let mut dep_keys = vec![DependencyKey::Path(path.clone())];

            dep_keys.extend(match external_repository {
                Some(_) => vec![],
                None => {
                    let mut loaded_deps = match get_tree_for_path(ctx, &path)? {
                        Some(tree) => find_load_dependencies(ctx, &tree)?,
                        None => Default::default(),
                    };

                    let prelude_deps = get_prelude_deps(ctx)?;
                    loaded_deps.extend(prelude_deps);
                    loaded_deps
                        .into_iter()
                        .map(DependencyKey::BazelBuildFile)
                        .collect()
                }
            });

            // Every package has an implicit dependency on the `WORKSPACE` file.
            dep_keys.push(DependencyKey::BazelBuildFile(Label {
                external_repository: None,
                path_components: Vec::new(),
                target_name: TargetName::Name("WORKSPACE".to_string()),
            }));

            Ok((
                "BazelPackage",
                Some(label),
                dep_keys.into_iter().map(KeyOrPath::Key).collect(),
            ))
        }

        DependencyKey::BazelBuildFile(
            label @ Label {
                external_repository,
                path_components,
                target_name,
            },
        ) => {
            let mut dep_keys = match (external_repository, target_name) {
                (Some(_), _) => Vec::new(),
                (None, TargetName::Ellipsis) => {
                    return Err(Error::Bug(format!(
                        "Got label referring to a ellipsis, but it should be a BUILD or .bzl file: {:?}",
                        label
                    )));
                }

                (None, TargetName::Name(target_name)) => {
                    let path: PathBuf = {
                        let mut path: PathBuf = path_components.iter().collect();
                        path.push(target_name);
                        path
                    };
                    let mut dep_keys = vec![DependencyKey::Path(path.clone())];

                    let loaded_deps = match ctx.head_tree.get_path(&path) {
                        Ok(tree_entry) => {
                            if is_tree_entry_relevant_to_build_graph(&tree_entry) {
                                extract_load_statements_from_tree_entry(ctx, &tree_entry)?
                            } else {
                                Default::default()
                            }
                        }
                        Err(e) if e.code() == git2::ErrorCode::NotFound => Default::default(),
                        Err(e) => return Err(Error::ReadTreeEntry(e)),
                    };

                    dep_keys.extend(
                        loaded_deps
                            .into_iter()
                            .map(DependencyKey::BazelBuildFile)
                            .filter(|key| dep_key != key),
                    );

                    dep_keys
                }
            };

            // Every `.bzl` file (or similar) has an implicit dependency on the
            // `WORKSPACE` file. However, the `WORKSPACE` file itself may `load`
            // `.bzl` files in the repository. To avoid a circular dependency,
            // use only the textual hash of the WORKSPACE as the dependency key
            // here.
            dep_keys.push(DependencyKey::Path("WORKSPACE".into()));

            Ok((
                "BazelBuildFile",
                Some(label),
                dep_keys.into_iter().map(KeyOrPath::Key).collect(),
            ))
        }

        DependencyKey::Path(path) => Ok(("Path", None, vec![KeyOrPath::Path(path)])),

        DependencyKey::DummyForTesting(inner_dep_key) => Ok((
            "DummyForTesting",
            None,
            vec![KeyOrPath::Key(inner_dep_key.as_ref().clone())],
        )),
    }
}