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 ©_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(())
}