fn apply_portal_mappings(
    portal_list: Vec<PortalMapping>,
    manifest: &mut Manifest,
    old_files: &mut Vec<PathBuf>,
) -> anyhow::Result<()> {
    let mut hash_cache: HashMap<PathBuf, String> = HashMap::new();
    let mut create_portals = Vec::new();

    for portal in portal_list {
        let (create, is_new) = if matches!(portal.target.try_exists(), Ok(true)) {
            let mut target_hash = String::new();
            let already_matches = match portal.file_type {
                FileType::Link => is_matching_symlink(&portal.target, &portal.source),
                FileType::Copy => {
                    portal.target.is_file() && !portal.target.is_symlink() && {
                        target_hash = calculate_file_hash(&portal.target)?;
                        &target_hash
                    } == {
                        if let Some(cache) = hash_cache.get(&portal.source) {
                            cache
                        } else {
                            calculate_file_hash(&portal.source).map(|h| {
                                hash_cache.insert(portal.source.clone(), h);
                                hash_cache.get(&portal.source).unwrap()
                            })?
                        }
                    }
                }
            };

            if already_matches {
                #[cfg(test)]
                DO_NOTHING.set(true);

                match portal.file_type {
                    FileType::Link => {
                        manifest.inner.insert(
                            portal.target.clone(),
                            ManifestType::Link {
                                source: portal.source.clone(),
                            },
                        );
                    }
                    FileType::Copy => {
                        let hash = if let Some(s) = hash_cache.get(&portal.source) {
                            s.to_string()
                        } else {
                            match calculate_file_hash(&portal.source) {
                                Ok(hash) => {
                                    hash_cache.insert(portal.source.clone(), hash.clone());
                                    hash
                                }
                                Err(e) => {
                                    log::error!("{e}");
                                    String::new()
                                }
                            }
                        };
                        manifest
                            .inner
                            .insert(portal.target.clone(), ManifestType::Copy { hash });
                    }
                }

                (false, true)
            } else {
                let is_managed = match manifest.inner.get(&portal.target) {
                    Some(ManifestType::Link { source }) => {
                        is_matching_symlink(&portal.target, source)
                    }
                    Some(ManifestType::Copy { hash }) => {
                        let h = if target_hash.is_empty() {
                            calculate_file_hash(&portal.target)?
                        } else {
                            target_hash
                        };
                        h == *hash
                    }
                    _ => false,
                };

                if is_managed {
                    (true, true)
                } else {
                    #[cfg(test)]
                    {
                        PROMPT.set(true);
                        (OVERWRITE.get(), OVERWRITE.get())
                    }
                    #[cfg(not(test))]
                    {
                        use crate::prompt::{Prompt, PromptError};

                        match Prompt::new(
                            format!("{} already exists", &portal.target.display()),
                            "overwrite",
                        )
                        .options(vec![('o', "overwrite"), ('s', "skip"), ('q', "quit")])
                        .print()
                        .map_err(PromptError::Io)?
                        {
                            "overwrite" => (true, true),
                            "skip" => (false, false),
                            "quit" => anyhow::bail!(PromptError::Quit),
                            _ => unreachable!(),
                        }
                    }
                }
            }
        } else {
            (true, true)
        };

        if is_new {
            if let Some(i) = old_files.iter().position(|p| p == &portal.target) {
                old_files.swap_remove(i);
            }
        }
        if create {
            create_portals.push(portal);
        }
    }

    fn remove_path(path: &Path) {
        if matches!(path.try_exists(), Ok(false)) {
            return;
        }
        let result = if path.is_dir() {
            remove_dir_all(path)
        } else {
            remove_file(path)
        };
        if let Err(e) = result {
            log::error!("Failed to remove {}: {}", path.display(), e);
        };
    }

    for portal in create_portals {
        if let Some(parent) = portal.target.parent() {
            if let Err(e) = create_dir_all(parent) {
                log::error!(
                    "Failed to create parent directory for {}: {}",
                    portal.target.display(),
                    e
                );
                continue;
            }
        }

        match portal.file_type {
            FileType::Link => {
                remove_path(&portal.target);
                if let Err(e) = symlink(&portal.source, &portal.target) {
                    log::error!(
                        "Failed to create symlink {}: {}",
                        &portal.target.display(),
                        e
                    );
                } else {
                    manifest.inner.insert(
                        portal.target.clone(),
                        ManifestType::Link {
                            source: portal.source.clone(),
                        },
                    );
                };
            }
            FileType::Copy => {
                remove_path(&portal.target);
                if let Err(e) = copy(&portal.source, &portal.target) {
                    log::error!("Failed to copy file {}: {}", &portal.target.display(), e);
                } else {
                    let hash = if let Some(s) = hash_cache.get(&portal.source) {
                        s.to_string()
                    } else {
                        match calculate_file_hash(&portal.source) {
                            Ok(hash) => {
                                hash_cache.insert(portal.source, hash.clone());
                                hash
                            }
                            Err(e) => {
                                log::error!("{e}");
                                String::new()
                            }
                        }
                    };
                    manifest
                        .inner
                        .insert(portal.target, ManifestType::Copy { hash });
                }
            }
        }
    }

    Ok(())
}

refactor