Skip to content

fs: calling mkdir in fs.cp function can ignore EEXIST error

This PR mainly aims to solve the following problem. During the execution of the fsp.cp function, due to other file operations, the target directory of fsp.cp is created in parallel. The actual situation may be more complicated. Multiple file operations are executed concurrently, resulting in an error in the internal fsp.cp when calling mkdir, because the folder has been created by other file operations. In this case, you can actually ignore this error and continue with the subsequent file copying operation.

import { promises as fsp } from 'fs'

const src = 'T:/src/'
const dst = 'T:/out/'

try {
    await fsp.rm(dst, { recursive: true })
} catch { }

await Promise.all([
    fsp.cp(src, dst, {
        recursive: true,
        force: true,
        errorOnExist: false,
        mode: 0
    }),
    
    // example other file operations in parallel
    fsp.mkdir(dst, { recursive: true })
])

// throws EEXIST: file already exists, mkdir 'T:/out/'
// at mkdir()
// at mkDirAndCopy() lib/internal/fs/cp/cp.js
// at onDir() lib/internal/fs/cp/cp.js

The relevant code is in lib/internal/fs/cp/cp.js. destStat is empty here, it did not exist when checking the folder before.

function onDir(srcStat, destStat, src, dest, opts) {
  if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts);
  return copyDir(src, dest, opts);
}

async function mkDirAndCopy(srcMode, src, dest, opts) {
  await mkdir(dest);
  await copyDir(src, dest, opts);
  return setDestMode(dest, srcMode);
}

I want to ignore the EEXIST error thrown by mkdir

async function mkDirAndCopy(srcMode, src, dest, opts) {
  try {
    await mkdir(dest);
  } catch (error) {
    // If the folder already exists, skip it.
    if (error.code !== 'EEXIST')
      throw error;
  }

  await copyDir(src, dest, opts);
  return setDestMode(dest, srcMode);
}

Merge request reports

Loading