Repository: bevyengine/bevy
File: crates/bevy_asset/src/server/mod.rs (Rust)

Code before:
            infos: &AssetInfos,
            paths_to_reload: &mut HashSet<AssetPath<'static>>,
        ) {
            if let Some(dependents) = infos.loader_dependents.get(asset_path) {
                for dependent in dependents {
                    paths_to_reload.insert(dependent.to_owned());
                    queue_ancestors(dependent, infos, paths_to_reload);
                }
            }
        }

        let reload_parent_folders = |path: &PathBuf, source: &AssetSourceId<'static>| {
            for parent in path.ancestors().skip(1) {
                let parent_asset_path =
                    AssetPath::from(parent.to_path_buf()).with_source(source.clone());
                for folder_handle in infos.get_path_handles(&parent_asset_path) {
                    info!("Reloading folder {parent_asset_path} because the content has changed");
                    server.load_folder_internal(folder_handle.id(), parent_asset_path.clone());
                }
            }
        };

        let mut paths_to_reload = <HashSet<_>>::default();
        let mut reload_path = |path: PathBuf, source: &AssetSourceId<'static>| {
            let path = AssetPath::from(path).with_source(source);
            if infos.should_reload(&path) {
                queue_ancestors(&path, &infos, &mut paths_to_reload);
                paths_to_reload.insert(path);
            }
        };

        let mut handle_event = |source: AssetSourceId<'static>, event: AssetSourceEvent| {
            match event {
                // TODO: if the asset was processed and the processed file was changed, the first modified event
                // should be skipped?
                AssetSourceEvent::AddedAsset(path) => {
                    reload_parent_folders(&path, &source);
                    reload_path(path, &source);
                }
                AssetSourceEvent::ModifiedAsset(path) | AssetSourceEvent::ModifiedMeta(path) => {
                    reload_path(path, &source);
                }
                AssetSourceEvent::RenamedFolder { old, new } => {
                    reload_parent_folders(&old, &source);
                    reload_parent_folders(&new, &source);
                }
                AssetSourceEvent::RemovedAsset(path)
                | AssetSourceEvent::RemovedFolder(path)
                | AssetSourceEvent::AddedFolder(path) => {
                    reload_parent_folders(&path, &source);
                }

Review comment (suggestion):
I don't think this should_reload should be here? If you have an asset loader that loads a nested asset in "immediate" mode, I don't think a handle will be kept alive, but the loader_dependents will be updated, and we should trigger a reload for that root loader (since maybe previously its nested asset was missing and now its not missing.

Actually looks like `NestedLoader<_, _, _, Immediate>` doesn't even record the dependencies, which likely means it'll get out of sync right now. Funnnn. Regardless of that issue, I don't think we should be filtering on whether the handle is alive. The `loader_dependents` will be empty if the path is truly unused.

Code after:
            infos: &AssetInfos,
            paths_to_reload: &mut HashSet<AssetPath<'static>>,
        ) {
            if let Some(dependents) = infos.loader_dependents.get(asset_path) {
                for dependent in dependents {
                    paths_to_reload.insert(dependent.to_owned());
                    queue_ancestors(dependent, infos, paths_to_reload);
                }
            }
        }

        let reload_parent_folders = |path: &PathBuf, source: &AssetSourceId<'static>| {
            for parent in path.ancestors().skip(1) {
                let parent_asset_path =
                    AssetPath::from(parent.to_path_buf()).with_source(source.clone());
                for folder_handle in infos.get_path_handles(&parent_asset_path) {
                    info!("Reloading folder {parent_asset_path} because the content has changed");
                    server.load_folder_internal(folder_handle.id(), parent_asset_path.clone());
                }
            }
        };

        let mut paths_to_reload = <HashSet<_>>::default();
        let mut reload_path = |path: PathBuf, source: &AssetSourceId<'static>| {
            let path = AssetPath::from(path).with_source(source);
            queue_ancestors(&path, &infos, &mut paths_to_reload);
            paths_to_reload.insert(path);
        };

        let mut handle_event = |source: AssetSourceId<'static>, event: AssetSourceEvent| {
            match event {
                AssetSourceEvent::AddedAsset(path) => {
                    reload_parent_folders(&path, &source);
                    reload_path(path, &source);
                }
                // TODO: if the asset was processed and the processed file was changed, the first modified event
                // should be skipped?
                AssetSourceEvent::ModifiedAsset(path) | AssetSourceEvent::ModifiedMeta(path) => {
                    reload_path(path, &source);
                }
                AssetSourceEvent::RenamedFolder { old, new } => {
                    reload_parent_folders(&old, &source);
                    reload_parent_folders(&new, &source);
                }
                AssetSourceEvent::RemovedAsset(path)
                | AssetSourceEvent::RemovedFolder(path)
                | AssetSourceEvent::AddedFolder(path) => {
                    reload_parent_folders(&path, &source);
                }
                _ => {}
            }