From 6f2b2bc9958954f127e9974b7f2d31ba09e703b2 Mon Sep 17 00:00:00 2001 From: Sukka Date: Wed, 25 Oct 2023 06:32:43 +0800 Subject: [PATCH] Refactor `create*`/`ensure*` API to async/await (#1023) * Refactor `createFile` * Refactor `createLink` * Refactor `createSymlink` --- lib/ensure/file.js | 65 ++++++++++----------- lib/ensure/link.js | 54 ++++++++--------- lib/ensure/symlink-paths.js | 112 ++++++++++++++++++------------------ lib/ensure/symlink-type.js | 29 +++++----- lib/ensure/symlink.js | 73 ++++++++++------------- 5 files changed, 160 insertions(+), 173 deletions(-) diff --git a/lib/ensure/file.js b/lib/ensure/file.js index 15cc473c8..a55c2d963 100644 --- a/lib/ensure/file.js +++ b/lib/ensure/file.js @@ -1,50 +1,47 @@ 'use strict' -const u = require('universalify').fromCallback +const u = require('universalify').fromPromise const path = require('path') -const fs = require('graceful-fs') +const fs = require('../fs') const mkdir = require('../mkdirs') -function createFile (file, callback) { - function makeFile () { - fs.writeFile(file, '', err => { - if (err) return callback(err) - callback() - }) - } +async function createFile (file) { + let stats + try { + stats = await fs.stat(file) + } catch { } + if (stats && stats.isFile()) return - fs.stat(file, (err, stats) => { // eslint-disable-line handle-callback-err - if (!err && stats.isFile()) return callback() - const dir = path.dirname(file) - fs.stat(dir, (err, stats) => { - if (err) { - // if the directory doesn't exist, make it - if (err.code === 'ENOENT') { - return mkdir.mkdirs(dir, err => { - if (err) return callback(err) - makeFile() - }) - } - return callback(err) - } + const dir = path.dirname(file) - if (stats.isDirectory()) makeFile() - else { - // parent is not a directory - // This is just to cause an internal ENOTDIR error to be thrown - fs.readdir(dir, err => { - if (err) return callback(err) - }) - } - }) - }) + let dirStats = null + try { + dirStats = await fs.stat(dir) + } catch (err) { + // if the directory doesn't exist, make it + if (err.code === 'ENOENT') { + await mkdir.mkdirs(dir) + await fs.writeFile(file, '') + return + } else { + throw err + } + } + + if (dirStats.isDirectory()) { + await fs.writeFile(file, '') + } else { + // parent is not a directory + // This is just to cause an internal ENOTDIR error to be thrown + await fs.readdir(dir) + } } function createFileSync (file) { let stats try { stats = fs.statSync(file) - } catch {} + } catch { } if (stats && stats.isFile()) return const dir = path.dirname(file) diff --git a/lib/ensure/link.js b/lib/ensure/link.js index f6d67486b..c3d1c694d 100644 --- a/lib/ensure/link.js +++ b/lib/ensure/link.js @@ -1,39 +1,39 @@ 'use strict' -const u = require('universalify').fromCallback +const u = require('universalify').fromPromise const path = require('path') -const fs = require('graceful-fs') +const fs = require('../fs') const mkdir = require('../mkdirs') -const pathExists = require('../path-exists').pathExists +const { pathExists } = require('../path-exists') const { areIdentical } = require('../util/stat') -function createLink (srcpath, dstpath, callback) { - function makeLink (srcpath, dstpath) { - fs.link(srcpath, dstpath, err => { - if (err) return callback(err) - callback(null) - }) +async function createLink (srcpath, dstpath) { + let dstStat + try { + dstStat = await fs.lstat(dstpath) + } catch { + // ignore error } - fs.lstat(dstpath, (_, dstStat) => { - fs.lstat(srcpath, (err, srcStat) => { - if (err) { - err.message = err.message.replace('lstat', 'ensureLink') - return callback(err) - } - if (dstStat && areIdentical(srcStat, dstStat)) return callback(null) + let srcStat + try { + srcStat = await fs.lstat(srcpath) + } catch (err) { + err.message = err.message.replace('lstat', 'ensureLink') + throw err + } + + if (dstStat && areIdentical(srcStat, dstStat)) return + + const dir = path.dirname(dstpath) + + const dirExists = await pathExists(dir) + + if (!dirExists) { + await mkdir.mkdirs(dir) + } - const dir = path.dirname(dstpath) - pathExists(dir, (err, dirExists) => { - if (err) return callback(err) - if (dirExists) return makeLink(srcpath, dstpath) - mkdir.mkdirs(dir, err => { - if (err) return callback(err) - makeLink(srcpath, dstpath) - }) - }) - }) - }) + await fs.link(srcpath, dstpath) } function createLinkSync (srcpath, dstpath) { diff --git a/lib/ensure/symlink-paths.js b/lib/ensure/symlink-paths.js index 33cd76000..85dda475d 100644 --- a/lib/ensure/symlink-paths.js +++ b/lib/ensure/symlink-paths.js @@ -1,8 +1,10 @@ 'use strict' const path = require('path') -const fs = require('graceful-fs') -const pathExists = require('../path-exists').pathExists +const fs = require('../fs') +const { pathExists } = require('../path-exists') + +const u = require('universalify').fromPromise /** * Function that returns two types of paths, one relative to symlink, and one @@ -26,74 +28,74 @@ const pathExists = require('../path-exists').pathExists * the ability to pass in `relative to current working direcotry` paths. */ -function symlinkPaths (srcpath, dstpath, callback) { +async function symlinkPaths (srcpath, dstpath) { if (path.isAbsolute(srcpath)) { - return fs.lstat(srcpath, (err) => { - if (err) { - err.message = err.message.replace('lstat', 'ensureSymlink') - return callback(err) - } - return callback(null, { - toCwd: srcpath, - toDst: srcpath - }) - }) - } else { - const dstdir = path.dirname(dstpath) - const relativeToDst = path.join(dstdir, srcpath) - return pathExists(relativeToDst, (err, exists) => { - if (err) return callback(err) - if (exists) { - return callback(null, { - toCwd: relativeToDst, - toDst: srcpath - }) - } else { - return fs.lstat(srcpath, (err) => { - if (err) { - err.message = err.message.replace('lstat', 'ensureSymlink') - return callback(err) - } - return callback(null, { - toCwd: srcpath, - toDst: path.relative(dstdir, srcpath) - }) - }) - } - }) + try { + await fs.lstat(srcpath) + } catch (err) { + err.message = err.message.replace('lstat', 'ensureSymlink') + throw err + } + + return { + toCwd: srcpath, + toDst: srcpath + } + } + + const dstdir = path.dirname(dstpath) + const relativeToDst = path.join(dstdir, srcpath) + + const exists = await pathExists(relativeToDst) + if (exists) { + return { + toCwd: relativeToDst, + toDst: srcpath + } + } + + try { + await fs.lstat(srcpath) + } catch (err) { + err.message = err.message.replace('lstat', 'ensureSymlink') + throw err + } + + return { + toCwd: srcpath, + toDst: path.relative(dstdir, srcpath) } } function symlinkPathsSync (srcpath, dstpath) { - let exists if (path.isAbsolute(srcpath)) { - exists = fs.existsSync(srcpath) + const exists = fs.existsSync(srcpath) if (!exists) throw new Error('absolute srcpath does not exist') return { toCwd: srcpath, toDst: srcpath } - } else { - const dstdir = path.dirname(dstpath) - const relativeToDst = path.join(dstdir, srcpath) - exists = fs.existsSync(relativeToDst) - if (exists) { - return { - toCwd: relativeToDst, - toDst: srcpath - } - } else { - exists = fs.existsSync(srcpath) - if (!exists) throw new Error('relative srcpath does not exist') - return { - toCwd: srcpath, - toDst: path.relative(dstdir, srcpath) - } + } + + const dstdir = path.dirname(dstpath) + const relativeToDst = path.join(dstdir, srcpath) + const exists = fs.existsSync(relativeToDst) + if (exists) { + return { + toCwd: relativeToDst, + toDst: srcpath } } + + const srcExists = fs.existsSync(srcpath) + if (!srcExists) throw new Error('relative srcpath does not exist') + return { + toCwd: srcpath, + toDst: path.relative(dstdir, srcpath) + } } module.exports = { - symlinkPaths, + symlinkPaths: u(symlinkPaths), symlinkPathsSync } diff --git a/lib/ensure/symlink-type.js b/lib/ensure/symlink-type.js index 42dc0ce75..518558e53 100644 --- a/lib/ensure/symlink-type.js +++ b/lib/ensure/symlink-type.js @@ -1,22 +1,25 @@ 'use strict' -const fs = require('graceful-fs') +const fs = require('../fs') +const u = require('universalify').fromPromise -function symlinkType (srcpath, type, callback) { - callback = (typeof type === 'function') ? type : callback - type = (typeof type === 'function') ? false : type - if (type) return callback(null, type) - fs.lstat(srcpath, (err, stats) => { - if (err) return callback(null, 'file') - type = (stats && stats.isDirectory()) ? 'dir' : 'file' - callback(null, type) - }) -} +async function symlinkType (srcpath, type) { + if (type) return type -function symlinkTypeSync (srcpath, type) { let stats + try { + stats = await fs.lstat(srcpath) + } catch { + return 'file' + } + return (stats && stats.isDirectory()) ? 'dir' : 'file' +} + +function symlinkTypeSync (srcpath, type) { if (type) return type + + let stats try { stats = fs.lstatSync(srcpath) } catch { @@ -26,6 +29,6 @@ function symlinkTypeSync (srcpath, type) { } module.exports = { - symlinkType, + symlinkType: u(symlinkType), symlinkTypeSync } diff --git a/lib/ensure/symlink.js b/lib/ensure/symlink.js index 2b93052f0..a3d5f578e 100644 --- a/lib/ensure/symlink.js +++ b/lib/ensure/symlink.js @@ -1,65 +1,50 @@ 'use strict' -const u = require('universalify').fromCallback +const u = require('universalify').fromPromise const path = require('path') const fs = require('../fs') -const _mkdirs = require('../mkdirs') -const mkdirs = _mkdirs.mkdirs -const mkdirsSync = _mkdirs.mkdirsSync -const _symlinkPaths = require('./symlink-paths') -const symlinkPaths = _symlinkPaths.symlinkPaths -const symlinkPathsSync = _symlinkPaths.symlinkPathsSync +const { mkdirs, mkdirsSync } = require('../mkdirs') -const _symlinkType = require('./symlink-type') -const symlinkType = _symlinkType.symlinkType -const symlinkTypeSync = _symlinkType.symlinkTypeSync +const { symlinkPaths, symlinkPathsSync } = require('./symlink-paths') +const { symlinkType, symlinkTypeSync } = require('./symlink-type') -const pathExists = require('../path-exists').pathExists +const { pathExists } = require('../path-exists') const { areIdentical } = require('../util/stat') -function createSymlink (srcpath, dstpath, type, callback) { - callback = (typeof type === 'function') ? type : callback - type = (typeof type === 'function') ? false : type +async function createSymlink (srcpath, dstpath, type) { + let stats + try { + stats = await fs.lstat(dstpath) + } catch { } - fs.lstat(dstpath, (err, stats) => { - if (!err && stats.isSymbolicLink()) { - Promise.all([ - fs.stat(srcpath), - fs.stat(dstpath) - ]).then(([srcStat, dstStat]) => { - if (areIdentical(srcStat, dstStat)) return callback(null) - _createSymlink(srcpath, dstpath, type, callback) - }) - } else _createSymlink(srcpath, dstpath, type, callback) - }) -} + if (stats && stats.isSymbolicLink()) { + const [srcStat, dstStat] = await Promise.all([ + fs.stat(srcpath), + fs.stat(dstpath) + ]) + + if (areIdentical(srcStat, dstStat)) return + } + + const relative = await symlinkPaths(srcpath, dstpath) + srcpath = relative.toDst + const toType = await symlinkType(relative.toCwd, type) + const dir = path.dirname(dstpath) + + if (!(await pathExists(dir))) { + await mkdirs(dir) + } -function _createSymlink (srcpath, dstpath, type, callback) { - symlinkPaths(srcpath, dstpath, (err, relative) => { - if (err) return callback(err) - srcpath = relative.toDst - symlinkType(relative.toCwd, type, (err, type) => { - if (err) return callback(err) - const dir = path.dirname(dstpath) - pathExists(dir, (err, dirExists) => { - if (err) return callback(err) - if (dirExists) return fs.symlink(srcpath, dstpath, type, callback) - mkdirs(dir, err => { - if (err) return callback(err) - fs.symlink(srcpath, dstpath, type, callback) - }) - }) - }) - }) + return fs.symlink(srcpath, dstpath, toType) } function createSymlinkSync (srcpath, dstpath, type) { let stats try { stats = fs.lstatSync(dstpath) - } catch {} + } catch { } if (stats && stats.isSymbolicLink()) { const srcStat = fs.statSync(srcpath) const dstStat = fs.statSync(dstpath)