2019-06-06 12:33:11 +02:00
|
|
|
import path from 'path'
|
|
|
|
import fs from 'fs'
|
|
|
|
import { promisify } from 'util'
|
2020-03-29 00:27:09 +01:00
|
|
|
import { Sema } from 'next/dist/compiled/async-sema'
|
2019-06-06 12:33:11 +02:00
|
|
|
|
|
|
|
const mkdir = promisify(fs.mkdir)
|
|
|
|
const stat = promisify(fs.stat)
|
|
|
|
const readdir = promisify(fs.readdir)
|
|
|
|
const copyFile = promisify(fs.copyFile)
|
|
|
|
|
|
|
|
const COPYFILE_EXCL = fs.constants.COPYFILE_EXCL
|
|
|
|
|
|
|
|
export async function recursiveCopy(
|
|
|
|
source: string,
|
|
|
|
dest: string,
|
|
|
|
{
|
2019-11-15 22:53:59 +01:00
|
|
|
concurrency = 32,
|
|
|
|
overwrite = false,
|
2019-06-06 12:33:11 +02:00
|
|
|
filter = () => true,
|
2019-11-15 22:53:59 +01:00
|
|
|
}: {
|
|
|
|
concurrency?: number
|
|
|
|
overwrite?: boolean
|
|
|
|
filter?(path: string): boolean
|
|
|
|
} = {}
|
2019-06-06 12:33:11 +02:00
|
|
|
) {
|
|
|
|
const cwdPath = process.cwd()
|
|
|
|
const from = path.resolve(cwdPath, source)
|
|
|
|
const to = path.resolve(cwdPath, dest)
|
|
|
|
|
|
|
|
const sema = new Sema(concurrency)
|
|
|
|
|
|
|
|
async function _copy(item: string) {
|
|
|
|
const target = item.replace(from, to)
|
|
|
|
const stats = await stat(item)
|
|
|
|
|
|
|
|
await sema.acquire()
|
|
|
|
|
|
|
|
if (stats.isDirectory()) {
|
|
|
|
try {
|
|
|
|
await mkdir(target)
|
|
|
|
} catch (err) {
|
|
|
|
// do not throw `folder already exists` errors
|
|
|
|
if (err.code !== 'EEXIST') {
|
|
|
|
throw err
|
|
|
|
}
|
|
|
|
}
|
2019-11-15 22:53:59 +01:00
|
|
|
sema.release()
|
2019-06-06 12:33:11 +02:00
|
|
|
const files = await readdir(item)
|
|
|
|
await Promise.all(files.map(file => _copy(path.join(item, file))))
|
|
|
|
} else if (
|
|
|
|
stats.isFile() &&
|
|
|
|
// before we send the path to filter
|
|
|
|
// we remove the base path (from) and replace \ by / (windows)
|
|
|
|
filter(item.replace(from, '').replace(/\\/g, '/'))
|
|
|
|
) {
|
2019-11-15 22:53:59 +01:00
|
|
|
await copyFile(item, target, overwrite ? undefined : COPYFILE_EXCL)
|
|
|
|
sema.release()
|
2019-06-06 12:33:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
await _copy(from)
|
|
|
|
}
|