def copytree(src, dst, symlinks=False, ignore=None, hardlinks=False):
names = os.listdir(src)<EOL>if ignore is not None:<EOL><INDENT>ignored_names = ignore(src, names)<EOL><DEDENT>else:<EOL><INDENT>ignored_names = set()<EOL><DEDENT>if hardlinks:<EOL><INDENT>def copy(srcname, dstname):<EOL><INDENT>try:<EOL><INDENT>os.link(srcname, dstname)<EOL><DEDENT>except OSError:<EOL><INDENT>shutil.copy2(srcname, dstname)<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>copy = shutil.copy2<EOL><DEDENT>if not os.path.isdir(dst):<EOL><INDENT>os.makedirs(dst)<EOL><DEDENT>errors = []<EOL>for name in names:<EOL><INDENT>if name in ignored_names:<EOL><INDENT>continue<EOL><DEDENT>srcname = os.path.join(src, name)<EOL>dstname = os.path.join(dst, name)<EOL>try:<EOL><INDENT>if symlinks and os.path.islink(srcname):<EOL><INDENT>linkto = os.readlink(srcname)<EOL>os.symlink(linkto, dstname)<EOL><DEDENT>elif os.path.isdir(srcname):<EOL><INDENT>copytree(srcname, dstname, symlinks, ignore)<EOL><DEDENT>else:<EOL><INDENT>copy(srcname, dstname)<EOL><DEDENT><DEDENT>except (IOError, os.error) as why:<EOL><INDENT>errors.append((srcname, dstname, str(why)))<EOL><DEDENT>except shutil.Error as err:<EOL><INDENT>errors.extend(err.args[<NUM_LIT:0>])<EOL><DEDENT><DEDENT>try:<EOL><INDENT>shutil.copystat(src, dst)<EOL><DEDENT>except shutil.WindowsError:<EOL><INDENT>pass<EOL><DEDENT>except OSError as why:<EOL><INDENT>errors.extend((src, dst, str(why)))<EOL><DEDENT>if errors:<EOL><INDENT>raise shutil.Error(errors)<EOL><DEDENT>
copytree that supports hard-linking