154 lines
4.7 KiB
JavaScript
154 lines
4.7 KiB
JavaScript
const fs = require("fs");
|
|
const path = require("path");
|
|
const util = require("util");
|
|
const Promise = require("bluebird");
|
|
|
|
const read = require("read");
|
|
const readP = util.promisify(read);
|
|
|
|
const minimatch = require("minimatch");
|
|
|
|
// P H A S E 0
|
|
|
|
function checkIncludes(config) {
|
|
config.excludes = config.excludes || [];
|
|
if (!config.include || !config.include.length) {
|
|
return Promise.reject({
|
|
code: "NoIncludes",
|
|
message: "You need to specify files to upload - e.g. ['*', '**/*']"
|
|
});
|
|
} else {
|
|
return Promise.resolve(config);
|
|
}
|
|
}
|
|
|
|
function getPassword(config) {
|
|
if (config.password) {
|
|
return Promise.resolve(config);
|
|
} else {
|
|
let options = {
|
|
prompt:
|
|
"Password for " +
|
|
config.user +
|
|
"@" +
|
|
config.host +
|
|
" (ENTER for none): ",
|
|
default: "",
|
|
silent: true
|
|
};
|
|
return readP(options).then(res => {
|
|
let config2 = Object.assign(config, { password: res });
|
|
return config2;
|
|
});
|
|
}
|
|
}
|
|
|
|
// Analysing local firstory
|
|
|
|
function canIncludePath(includes, excludes, filePath) {
|
|
let go = (acc, item) =>
|
|
acc || minimatch(filePath, item, { matchBase: true });
|
|
let canInclude = includes.reduce(go, false);
|
|
|
|
// Now check whether the file should in fact be specifically excluded
|
|
if (canInclude) {
|
|
// if any excludes match return false
|
|
if (excludes) {
|
|
let go2 = (acc, item) =>
|
|
acc && !minimatch(filePath, item, { matchBase: true });
|
|
canInclude = excludes.reduce(go2, true);
|
|
}
|
|
}
|
|
// console.log("canIncludePath", include, filePath, res);
|
|
return canInclude;
|
|
}
|
|
|
|
// A method for parsing the source location and storing the information into a suitably formated object
|
|
function parseLocal(includes, excludes, localRootDir, relDir) {
|
|
// reducer
|
|
let handleItem = function(acc, item) {
|
|
const currItem = path.join(fullDir, item);
|
|
const newRelDir = path.relative(localRootDir, currItem);
|
|
|
|
if (fs.lstatSync(currItem).isDirectory()) {
|
|
// currItem is a directory. Recurse and attach to accumulator
|
|
let tmp = parseLocal(includes, excludes, localRootDir, newRelDir);
|
|
for (let key in tmp) {
|
|
if (tmp[key].length == 0) {
|
|
delete tmp[key];
|
|
}
|
|
}
|
|
return Object.assign(acc, tmp);
|
|
} else {
|
|
// currItem is a file
|
|
// acc[relDir] is always created at previous iteration
|
|
if (canIncludePath(includes, excludes, newRelDir)) {
|
|
// console.log("including", currItem);
|
|
acc[relDir].push(item);
|
|
return acc;
|
|
}
|
|
}
|
|
return acc;
|
|
};
|
|
|
|
const fullDir = path.join(localRootDir, relDir);
|
|
// Check if `startDir` is a valid location
|
|
if (!fs.existsSync(fullDir)) {
|
|
throw new Error(fullDir + " is not an existing location");
|
|
}
|
|
|
|
// Iterate through the contents of the `fullDir` of the current iteration
|
|
const files = fs.readdirSync(fullDir);
|
|
// Add empty array, which may get overwritten by subsequent iterations
|
|
let acc = {};
|
|
acc[relDir] = [];
|
|
const res = files.reduce(handleItem, acc);
|
|
return res;
|
|
}
|
|
|
|
function countFiles(filemap) {
|
|
return Object.values(filemap).reduce((acc, item) => acc.concat(item))
|
|
.length;
|
|
}
|
|
|
|
function deleteDir(ftp, dir) {
|
|
return ftp.list(dir).then(lst => {
|
|
let dirNames = lst
|
|
.filter(f => f.type == "d" && f.name != ".." && f.name != ".")
|
|
.map(f => path.posix.join(dir, f.name));
|
|
|
|
let fnames = lst
|
|
.filter(f => f.type != "d")
|
|
.map(f => path.posix.join(dir, f.name));
|
|
|
|
// delete sub-directories and then all files
|
|
return Promise.mapSeries(dirNames, dirName => {
|
|
// deletes everything in sub-directory, and then itself
|
|
return deleteDir(ftp, dirName).then(() => ftp.rmdir(dirName));
|
|
}).then(() => Promise.mapSeries(fnames, fname => ftp.delete(fname)));
|
|
});
|
|
}
|
|
|
|
mkDirExists = (ftp, dir) => {
|
|
// Make the directory using recursive expand
|
|
return ftp.mkdir(dir, true).catch(err => {
|
|
if (err.message.startsWith("EEXIST")) {
|
|
return Promise.resolve();
|
|
} else {
|
|
console.log("[mkDirExists]", err.message);
|
|
// console.log(Object.getOwnPropertyNames(err));
|
|
return Promise.reject(err);
|
|
}
|
|
});
|
|
};
|
|
|
|
module.exports = {
|
|
checkIncludes: checkIncludes,
|
|
getPassword: getPassword,
|
|
parseLocal: parseLocal,
|
|
canIncludePath: canIncludePath,
|
|
countFiles: countFiles,
|
|
mkDirExists: mkDirExists,
|
|
deleteDir: deleteDir
|
|
};
|