File::copyDirectoryTo doesn't preserve symlinks (macOS)

Copying a bundle or framework that has symlinks inside does not preserve the symbolic links. Instead physical deep copies are made. This pretty much renders Juce incapable of perfoming deployment and installation tasks.

I see that File::copyDirectoryTo uses NSFileManager internally, but somehow, according to Apple’s documentation, there doesn’t seem to be an option to preserve symlinks, so it is unclear how to fix this.

Isn’t there a system call on macOS that mimics a copy with Finder? What am I missing?

An experiment showed that using File::copyFileTo to copy a bundle or framework does the trick.

So if an application is required to determine whether to use copyFileTo or copyDirectoryTo, the remedy is to check for isBundle() first for any top-level item to copy.

Well, it turns out that isBundle() does not reliably recognize bundles you have created from files and folders yourself. I don’t know how common this is, but I’m building apps and bundles with automated build scripts a lot.

If you’re doing this also, you can use the following function to tell whether a File is to be copied with copyDirectoryTo vs. copyFileTo:

bool isCopiedAsDirectory (const File& source)
{
    if (! source.isDirectory())
        return false;
    
#if JUCE_MAC
    if (source.isBundle())
        return false;
    
    static const StringArray bundles =
        { ".app", ".bundle", ".framework", ".component", ".vst", ".vst3", ".aaxplugin", ".pkg", ".mpkg" };

    if (bundles.indexOf (source.getFileExtension()) >= 0)
        return false;
#endif
    return true;
}