public function symlinkAll(
        $source,
        $destination,
        $skipExisting = true,
        $recursive = false,
        $blacklist = [],
        $copy = false
    ) {
        if (!is_dir($destination)) {
            mkdir($destination);
        }

        // The symlink won't work if $source is a relative path.
        $source = realpath($source);

        // Files to always skip.
        $skip = ['.git', '.DS_Store'];
        $skip = array_merge($skip, $blacklist);

        $sourceDirectory = opendir($source);
        while ($file = readdir($sourceDirectory)) {
            // Skip symlinks, '.' and '..', and files in $skip.
            if ($file === '.' || $file === '..' || $this->inBlacklist($file, $skip) || is_link($source . '/' . $file)) {
                continue;
            }
            $sourceFile = $source . '/' . $file;
            $linkFile = $destination . '/' . $file;

            if ($recursive && !is_link($linkFile) && is_dir($linkFile) && is_dir($sourceFile)) {
                $this->symlinkAll($sourceFile, $linkFile, $skipExisting, $recursive, $blacklist, $copy);
                continue;
            } elseif (file_exists($linkFile)) {
                if ($skipExisting) {
                    continue;
                } else {
                    throw new \Exception('File exists: ' . $linkFile);
                }
            } elseif (is_link($linkFile)) {
                // This is a broken link. Remove it.
                $this->remove($linkFile);
            }

            if ($copy) {
                $this->copyAll($sourceFile, $linkFile, $blacklist);
            } else {
                $this->symlink($sourceFile, $linkFile);
            }
        }
        closedir($sourceDirectory);
    }