mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Normalise root path in file_watcher (#12102)
# Objective - I hit an issue using the `file_watcher` feature to hot reload assets for my game. The change in this PR allows me to now hot reload assets. - The issue stemmed from my project being a multi crate workspace project structured like so: ``` └── my_game ├── my_game_core │ ├── src │ └── assets ├── my_game_editor │ └── src/main.rs └── my_game └── src/main.rs ``` - `my_game_core` is a crate that holds all my game logic and assets - `my_game` is the crate that creates the binary for my game (depends on the game logic and assets in `my_game_core`) - `my_game_editor` is an editor tool for my game (it also depends on the game logic and assets in `my_game_core`) Whilst running `my_game` and `my_game_editor` from cargo during development I would use `AssetPlugin` like so: ```rust default_plugins.set(AssetPlugin { watch_for_changes_override: Some(true), file_path: "../my_game_core/assets".to_string(), ..Default::default() }) ``` This works fine; bevy picks up the assets. However on saving an asset I would get the following panic from `file_watcher`. It wouldn't kill the app, but I wouldn't see the asset hot reload: ``` thread 'notify-rs debouncer loop' panicked at /Users/ian/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_asset-0.12.1/src/io/file/file_watcher.rs:48:58: called `Result::unwrap()` on an `Err` value: StripPrefixError(()) note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` ## Solution - The solution is to collapse dot segments in the root asset path `FileWatcher` is using - There was already bevy code to do this in `AssetPath`, so I extracted that code so it could be reused in `FileWatcher`
This commit is contained in:
parent
bc2ddce432
commit
14042b1e34
2 changed files with 28 additions and 29 deletions
|
@ -1,4 +1,5 @@
|
|||
use crate::io::{AssetSourceEvent, AssetWatcher};
|
||||
use crate::path::normalize_path;
|
||||
use bevy_log::error;
|
||||
use bevy_utils::Duration;
|
||||
use crossbeam_channel::Sender;
|
||||
|
@ -28,7 +29,7 @@ impl FileWatcher {
|
|||
sender: Sender<AssetSourceEvent>,
|
||||
debounce_wait_time: Duration,
|
||||
) -> Result<Self, notify::Error> {
|
||||
let root = super::get_base_path().join(root);
|
||||
let root = normalize_path(super::get_base_path().join(root).as_path());
|
||||
let watcher = new_asset_event_debouncer(
|
||||
root.clone(),
|
||||
debounce_wait_time,
|
||||
|
|
|
@ -431,34 +431,13 @@ impl<'a> AssetPath<'a> {
|
|||
_ => rpath,
|
||||
};
|
||||
|
||||
let mut result_path = PathBuf::new();
|
||||
if !is_absolute && source.is_none() {
|
||||
for elt in base_path.iter() {
|
||||
if elt == "." {
|
||||
// Skip
|
||||
} else if elt == ".." {
|
||||
if !result_path.pop() {
|
||||
// Preserve ".." if insufficient matches (per RFC 1808).
|
||||
result_path.push(elt);
|
||||
}
|
||||
} else {
|
||||
result_path.push(elt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for elt in rpath.iter() {
|
||||
if elt == "." {
|
||||
// Skip
|
||||
} else if elt == ".." {
|
||||
if !result_path.pop() {
|
||||
// Preserve ".." if insufficient matches (per RFC 1808).
|
||||
result_path.push(elt);
|
||||
}
|
||||
} else {
|
||||
result_path.push(elt);
|
||||
}
|
||||
}
|
||||
let mut result_path = if !is_absolute && source.is_none() {
|
||||
base_path
|
||||
} else {
|
||||
PathBuf::new()
|
||||
};
|
||||
result_path.push(rpath);
|
||||
result_path = normalize_path(result_path.as_path());
|
||||
|
||||
Ok(AssetPath {
|
||||
source: match source {
|
||||
|
@ -723,6 +702,25 @@ impl FromReflect for AssetPath<'static> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Normalizes the path by collapsing all occurrences of '.' and '..' dot-segments where possible
|
||||
/// as per [RFC 1808](https://datatracker.ietf.org/doc/html/rfc1808)
|
||||
pub(crate) fn normalize_path(path: &Path) -> PathBuf {
|
||||
let mut result_path = PathBuf::new();
|
||||
for elt in path.iter() {
|
||||
if elt == "." {
|
||||
// Skip
|
||||
} else if elt == ".." {
|
||||
if !result_path.pop() {
|
||||
// Preserve ".." if insufficient matches (per RFC 1808).
|
||||
result_path.push(elt);
|
||||
}
|
||||
} else {
|
||||
result_path.push(elt);
|
||||
}
|
||||
}
|
||||
result_path
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::AssetPath;
|
||||
|
|
Loading…
Reference in a new issue