Swap-Aggregator-Subgraph/node_modules/fs-jetpack/lib/dir.js
Richa-iitr d211083153 Revert "Revert "added handler""
This reverts commit c36ee8c5ca.
2022-07-03 07:30:05 +05:30

242 lines
6.4 KiB
JavaScript

"use strict";
const pathUtil = require("path");
const fs = require("./utils/fs");
const modeUtil = require("./utils/mode");
const validate = require("./utils/validate");
const remove = require("./remove");
const validateInput = (methodName, path, criteria) => {
const methodSignature = `${methodName}(path, [criteria])`;
validate.argument(methodSignature, "path", path, ["string"]);
validate.options(methodSignature, "criteria", criteria, {
empty: ["boolean"],
mode: ["string", "number"]
});
};
const getCriteriaDefaults = passedCriteria => {
const criteria = passedCriteria || {};
if (typeof criteria.empty !== "boolean") {
criteria.empty = false;
}
if (criteria.mode !== undefined) {
criteria.mode = modeUtil.normalizeFileMode(criteria.mode);
}
return criteria;
};
const generatePathOccupiedByNotDirectoryError = path => {
return new Error(
`Path ${path} exists but is not a directory. Halting jetpack.dir() call for safety reasons.`
);
};
// ---------------------------------------------------------
// Sync
// ---------------------------------------------------------
const checkWhatAlreadyOccupiesPathSync = path => {
let stat;
try {
stat = fs.statSync(path);
} catch (err) {
// Detection if path already exists
if (err.code !== "ENOENT") {
throw err;
}
}
if (stat && !stat.isDirectory()) {
throw generatePathOccupiedByNotDirectoryError(path);
}
return stat;
};
const createBrandNewDirectorySync = (path, opts) => {
const options = opts || {};
try {
fs.mkdirSync(path, options.mode);
} catch (err) {
if (err.code === "ENOENT") {
// Parent directory doesn't exist. Need to create it first.
createBrandNewDirectorySync(pathUtil.dirname(path), options);
// Now retry creating this directory.
fs.mkdirSync(path, options.mode);
} else if (err.code === "EEXIST") {
// The path already exists. We're fine.
} else {
throw err;
}
}
};
const checkExistingDirectoryFulfillsCriteriaSync = (path, stat, criteria) => {
const checkMode = () => {
const mode = modeUtil.normalizeFileMode(stat.mode);
if (criteria.mode !== undefined && criteria.mode !== mode) {
fs.chmodSync(path, criteria.mode);
}
};
const checkEmptiness = () => {
if (criteria.empty) {
// Delete everything inside this directory
const list = fs.readdirSync(path);
list.forEach(filename => {
remove.sync(pathUtil.resolve(path, filename));
});
}
};
checkMode();
checkEmptiness();
};
const dirSync = (path, passedCriteria) => {
const criteria = getCriteriaDefaults(passedCriteria);
const stat = checkWhatAlreadyOccupiesPathSync(path);
if (stat) {
checkExistingDirectoryFulfillsCriteriaSync(path, stat, criteria);
} else {
createBrandNewDirectorySync(path, criteria);
}
};
// ---------------------------------------------------------
// Async
// ---------------------------------------------------------
const checkWhatAlreadyOccupiesPathAsync = path => {
return new Promise((resolve, reject) => {
fs.stat(path)
.then(stat => {
if (stat.isDirectory()) {
resolve(stat);
} else {
reject(generatePathOccupiedByNotDirectoryError(path));
}
})
.catch(err => {
if (err.code === "ENOENT") {
// Path doesn't exist
resolve(undefined);
} else {
// This is other error that nonexistent path, so end here.
reject(err);
}
});
});
};
// Delete all files and directores inside given directory
const emptyAsync = path => {
return new Promise((resolve, reject) => {
fs.readdir(path)
.then(list => {
const doOne = index => {
if (index === list.length) {
resolve();
} else {
const subPath = pathUtil.resolve(path, list[index]);
remove.async(subPath).then(() => {
doOne(index + 1);
});
}
};
doOne(0);
})
.catch(reject);
});
};
const checkExistingDirectoryFulfillsCriteriaAsync = (path, stat, criteria) => {
return new Promise((resolve, reject) => {
const checkMode = () => {
const mode = modeUtil.normalizeFileMode(stat.mode);
if (criteria.mode !== undefined && criteria.mode !== mode) {
return fs.chmod(path, criteria.mode);
}
return Promise.resolve();
};
const checkEmptiness = () => {
if (criteria.empty) {
return emptyAsync(path);
}
return Promise.resolve();
};
checkMode()
.then(checkEmptiness)
.then(resolve, reject);
});
};
const createBrandNewDirectoryAsync = (path, opts) => {
const options = opts || {};
return new Promise((resolve, reject) => {
fs.mkdir(path, options.mode)
.then(resolve)
.catch(err => {
if (err.code === "ENOENT") {
// Parent directory doesn't exist. Need to create it first.
createBrandNewDirectoryAsync(pathUtil.dirname(path), options)
.then(() => {
// Now retry creating this directory.
return fs.mkdir(path, options.mode);
})
.then(resolve)
.catch(err2 => {
if (err2.code === "EEXIST") {
// Hmm, something other have already created the directory?
// No problem for us.
resolve();
} else {
reject(err2);
}
});
} else if (err.code === "EEXIST") {
// The path already exists. We're fine.
resolve();
} else {
reject(err);
}
});
});
};
const dirAsync = (path, passedCriteria) => {
return new Promise((resolve, reject) => {
const criteria = getCriteriaDefaults(passedCriteria);
checkWhatAlreadyOccupiesPathAsync(path)
.then(stat => {
if (stat !== undefined) {
return checkExistingDirectoryFulfillsCriteriaAsync(
path,
stat,
criteria
);
}
return createBrandNewDirectoryAsync(path, criteria);
})
.then(resolve, reject);
});
};
// ---------------------------------------------------------
// API
// ---------------------------------------------------------
exports.validateInput = validateInput;
exports.sync = dirSync;
exports.createSync = createBrandNewDirectorySync;
exports.async = dirAsync;
exports.createAsync = createBrandNewDirectoryAsync;