Skip to content

Commit

Permalink
fix: support running embedded_path! from a "remote" crate
Browse files Browse the repository at this point in the history
This includes if cargo is building a crate that depends on some crates.io or git
repo crate that contains embedded assets.
  • Loading branch information
bonsairobo committed Nov 6, 2023
1 parent 21eb807 commit 09f2b91
Showing 1 changed file with 50 additions and 5 deletions.
55 changes: 50 additions & 5 deletions crates/bevy_asset/src/io/embedded/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,57 @@ macro_rules! embedded_path {
}};

($source_path: expr, $path_str: expr) => {{
let crate_name = module_path!().split(':').next().unwrap();
let file_path = std::path::Path::new(file!());
let after_src = file_path
.strip_prefix($source_path)
.unwrap_or_else(|_| panic!("{file_path:?} does not have prefix {}", $source_path));
/// Strip `src_path` from `file_path` and return only the suffix that
/// follows.
fn split_path(
src_path: &std::path::Path,
file_path: &std::path::Path,
) -> std::path::PathBuf {
if file_path.is_absolute() {
// Absolute paths show up if this macro is being invoked by an
// external dependency, e.g. one that's being checked out from a
// crates repo or git.
//
// It's possible that `file_path` includes some components
// preceding `src_path`. For example:
//
// src_path = src
// file_path = /path/to/crate/src/foo.rs
//
// We want to return "foo.rs".
//
// # stupid edge case
//
// There is an annoying edge case where if `src_path` shows up
// twice after the workspace root:
//
// src_path = src
// file_path = /path/to/crate/src/src/foo.rs
//
// Then we won't know which one is legit. We can't fix this case
// without knowing the actual path to the external crate.
let mut maybe_parent = file_path.parent();
while let Some(parent) = maybe_parent {
if parent.ends_with(src_path) {
return file_path.strip_prefix(parent).unwrap().into();
}
maybe_parent = parent.parent();
}
panic!("Failed to find src_path {src_path:?} in {file_path:?}")
} else {
// Relative paths show up if this macro is being invoked by a
// local crate. In this case we know the relative path is a sub-
// path of the workspace root.
file_path
.strip_prefix(src_path)
.unwrap_or_else(|_| panic!("{file_path:?} does not have prefix {src_path:?}"))
.into()
}
}

let after_src = split_path($source_path.as_ref(), file!().as_ref());
let file_path = after_src.parent().unwrap().join($path_str);
let crate_name = module_path!().split(':').next().unwrap();
std::path::Path::new(crate_name).join(file_path)
}};
}
Expand Down

0 comments on commit 09f2b91

Please sign in to comment.