fn main()

in antlir/bzl/genrule/extractor/extract.rs [207:334]


fn main() -> Result<()> {
    let opt = ExtractOpts::from_args();
    let top_src_dir = opt.src_dir;
    let top_dst_dir = opt.dst_dir;
    let target = opt.target;
    let output_dir = opt.output_dir;

    let binaries: Vec<Binary> = opt
        .binaries
        .into_iter()
        .map(|s| Binary::new(top_src_dir.clone(), top_src_dir.force_join(&s), s.into()))
        .collect::<Result<_>>()?;

    let extract_files: Vec<_> = binaries
        .into_iter()
        .map(|bin| bin.extracts())
        .collect::<Result<Vec<_>>>()?
        .into_iter()
        .flatten()
        .collect();

    // map dst -> src to dedupe file copies for libraries that might be depended
    // on multiple times
    let copy_files: HashMap<PathBuf, PathBuf> = extract_files
        .into_iter()
        .map(|ex| {
            let dst = top_dst_dir.force_join(ex.to);
            let src = fs::canonicalize(ex.from)
                .unwrap()
                .strip_prefix(top_src_dir.clone())
                .unwrap()
                .to_path_buf();
            (dst, src)
        })
        .collect();

    let copied_dirs: BTreeSet<_> = copy_files
        .keys()
        .flat_map(|k| k.parents())
        // if not under top_dst_dir, then ignore it (ex: it is the parent of top_dst_dir)
        .filter_map(|k| k.strip_prefix(&top_dst_dir).ok().map(|p| p.to_path_buf()))
        .map(|k| (k.components().count(), k))
        .collect();

    let mut features = vec![];
    // "clone" feature for each files to copy
    for (dst, src) in &copy_files {
        features.push(json!(
            {
                "remove_paths": [
                    {
                        "must_exist": false,
                        "path": dst
                    }
                ],
                "target": target
            }
        ));
        features.push(json!(
            {
                "clone": [
                    {
                        "dest": dst,
                        "omit_outer_dir": false,
                        "pre_existing_dest": false,
                        "source": {
                            "content_hash": null,
                            "generator": null,
                            "generator_args": [],
                            "layer": {
                                    "__BUCK_LAYER_TARGET": target
                            },
                            "path": src,
                            "source": null
                        },
                        "source_layer": {
                        "__BUCK_LAYER_TARGET": target
                        }
                    }
                ],
                "target": target
            }
        ));
    }

    // "ensure_subdirs_exist" feature for each dirs to copy
    for (_, dst_rel) in copied_dirs.iter().rev() {
        if dst_rel.as_os_str().is_empty() {
            continue;
        }
        let dst_dir = top_dst_dir.force_join(&dst_rel);
        let maybe_src_dir = top_src_dir.force_join(dst_rel);
        let mut mode = json!(null);
        // do a bottom-up traversal of all the destination directories, copying the
        // permission bits from the source where possible
        if maybe_src_dir.exists() {
            let meta = fs::metadata(&maybe_src_dir).with_context(|| {
                format!("failed to get permissions from src {:?}", &maybe_src_dir)
            })?;
            mode = json!(meta.permissions().mode() & 0o7777);
        } else {
            warn!(
                LOGGER,
                "leaving default mode for {:?}, because {:?} did not exist", dst_dir, maybe_src_dir
            );
        }
        features.push(json!({
            "ensure_subdirs_exist": [
                {
                    "into_dir": dst_dir.parent().unwrap(),
                    "mode": mode,
                    "subdirs_to_create": dst_dir.file_name().unwrap().to_str().unwrap(),
                    "user_group": null
                }
            ],
            "target": target
        }));
    }

    serde_json::to_writer(
        &File::create(Path::new(&output_dir).force_join("feature.json"))?,
        &json!({
            "features": features,
            "target": target
        }),
    )?;
    Ok(())
}