def render_recursive_template(template_folder, info, out_folder, preserve=None, dry_run=False):
    if isinstance(preserve, str):
        raise ArgumentError("You must pass a list of strings to preserve, not a string", preserve=preserve)
    if preserve is None:
        preserve = []
    preserve = set(preserve)
    template_dir = resource_path('templates', expect='folder')
    indir = os.path.join(template_dir, template_folder)
    if not os.path.exists(indir):
        raise ArgumentError("Input template folder for recursive template not found",
                            template_folder=template_folder, absolute_path=indir)
    elif not os.path.isdir(indir):
        raise ArgumentError("Input template folder is not a directory",
                            template_folder=template_folder, absolute_path=indir)
    create_dirs = []
    file_map = {}
    for dirpath, dirs, files in os.walk(indir):
        for file in files:
            in_abspath = os.path.abspath(os.path.join(dirpath, file))
            in_path = os.path.relpath(os.path.join(dirpath, file), start=indir)
            if file.endswith(".tpl") and not in_path in preserve:
                out_path = in_path[:-4]
            else:
                out_path = in_path
            file_map[out_path] = (in_path, in_abspath)
            for folder in dirs:
                dir_path = os.path.relpath(os.path.join(dirpath, folder), start=indir)
                create_dirs.append(dir_path)
    if not dry_run:
        for folder in create_dirs:
            out_path = os.path.join(out_folder, folder)
            if not os.path.isdir(out_path):
                os.makedirs(out_path)
        for out_rel, (in_path, in_abspath) in file_map.items():
            out_path = os.path.join(out_folder, out_rel)
            if in_path in preserve or not in_path.endswith(".tpl"):
                shutil.copyfile(in_abspath, out_path)
            else:
                in_template_path = os.path.join(template_folder, in_path).replace(os.path.sep, '/')
                render_template(in_template_path, info, out_path=out_path)
    return file_map, create_dirs