(source: string, destination: string)
| 870 | * @throws FileSystemAccessError for any other error. |
| 871 | */ |
| 872 | export async function copy(source: string, destination: string): Promise<void> { |
| 873 | // We must proactively check if the source is a directory. |
| 874 | // On modern Linux kernels (6.x+), the `copy_file_range` system call used by |
| 875 | // Node.js may return success (0 bytes copied) when the source is a directory |
| 876 | // instead of throwing EISDIR. Node.js interprets this 0-byte success as a |
| 877 | // completed operation, resulting in no error being thrown. |
| 878 | if (await isDirectory(source)) { |
| 879 | throw new IsDirectoryError(source, undefined); |
| 880 | } |
| 881 | |
| 882 | try { |
| 883 | await fsPromises.copyFile(source, destination); |
| 884 | } catch (e) { |
| 885 | ensureNodeErrnoExceptionError(e); |
| 886 | if (e.code === "ENOENT") { |
| 887 | if (!(await exists(source))) { |
| 888 | throw new FileNotFoundError(source, e); |
| 889 | } |
| 890 | if (!(await exists(destination))) { |
| 891 | throw new FileNotFoundError(destination, e); |
| 892 | } |
| 893 | } |
| 894 | |
| 895 | // On linux, trying to copy a directory will throw EISDIR, |
| 896 | // on Windows it will throw EPERM, and on macOS it will throw ENOTSUP. |
| 897 | if (e.code === "EISDIR" || e.code === "EPERM" || e.code === "ENOTSUP") { |
| 898 | if (await isDirectory(source)) { |
| 899 | throw new IsDirectoryError(source, e); |
| 900 | } |
| 901 | if (await isDirectory(destination)) { |
| 902 | throw new IsDirectoryError(destination, e); |
| 903 | } |
| 904 | } |
| 905 | |
| 906 | throw new FileSystemAccessError(e.message, e); |
| 907 | } |
| 908 | } |
| 909 | |
| 910 | /** |
| 911 | * Moves a file or directory from a source to a destination. If the source is a |
no test coverage detected