123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- 'use strict';
- var path = require('path');
- var fs = require('fs');
- var glob = require('glob');
- var mkdirp = require('mkdirp');
- var untildify = require('untildify');
- var through = require('through2').obj;
- var noms = require('noms').obj;
- function toStream(array) {
- var length = array.length;
- var i = 0;
- return noms(function (done) {
- if (i >= length) {
- this.push(null);
- }
- this.push(array[i++]);
- done();
- });
- }
- function depth(string) {
- return path.normalize(string).split(path.sep).length - 1;
- }
- function dealWith(inPath, up) {
- if (!up) {
- return inPath;
- }
- if (up === true) {
- return path.basename(inPath);
- }
- if (depth(inPath) < up) {
- throw new Error('cant go up that far');
- }
- return path.join.apply(path, path.normalize(inPath).split(path.sep).slice(up));
- }
- var copyFile = _copyFile;
- function _copyFile (src, dst, opts, callback) {
- fs.createReadStream(src)
- .pipe(fs.createWriteStream(dst, {
- mode: opts.mode
- }))
- .once('error', callback)
- .once('finish', function () {
- fs.chmod(dst, opts.mode, function (err) {
- callback(err);
- })
- })
- }
- if (fs.copyFile) {
- copyFile = function (src, dst, opts, callback) {
- fs.copyFile(src, dst, callback);
- }
- }
- function makeDebug(config) {
- if (config.verbose) {
- return function (thing) {
- console.log(thing);
- }
- }
- return function () {}
- }
- module.exports = copyFiles;
- function copyFiles(args, config, callback) {
- if (typeof config === 'function') {
- callback = config;
- config = {
- up:0
- };
- }
- if (typeof config !== 'object' && config) {
- config = {
- up: config
- };
- }
- var debug = makeDebug(config);
- var copied = false;
- var opts = config.up || 0;
- var soft = config.soft;
- if (typeof callback !== 'function') {
- throw new Error('callback is not optional');
- }
- var input = args.slice();
- var outDir = input.pop();
- var globOpts = {};
- if (config.exclude) {
- globOpts.ignore = config.exclude;
- }
- if (config.all) {
- globOpts.dot = true;
- }
- if (config.follow) {
- globOpts.follow = true;
- }
- outDir = outDir.startsWith('~') ? untildify(outDir) : outDir;
- toStream(input.map(function(srcP) {return srcP.startsWith('~') ? untildify(srcP) : srcP;}))
- .pipe(through(function (pathName, _, next) {
- var self = this;
- glob(pathName, globOpts, function (err, paths) {
- if (err) {
- return next(err);
- }
- paths.forEach(function (unglobbedPath) {
- debug(`unglobed path: ${unglobbedPath}`);
- self.push(unglobbedPath);
- });
- next();
- });
- }))
- .on('error', callback)
- .pipe(through(function (pathName, _, next) {
- fs.stat(pathName, function (err, pathStat) {
- if (err) {
- return next(err);
- }
- var outName = path.join(outDir, dealWith(pathName, opts));
- function done(){
- mkdirp(path.dirname(outName)).then(()=>{
- next(null, {
- pathName: pathName,
- pathStat: pathStat
- });
- }, next);
- }
- if (pathStat.isDirectory()) {
- debug(`skipping, is directory: ${pathName}`)
- return next();
- }
- if (!pathStat.isFile()) {
- return next(new Error('how can it be neither file nor folder?'))
- }
- if (!soft) {
- return done();
- }
- fs.stat(outName, function(err){
- if(!err){
- //file exists
- return next()
- }
- if (err.code === 'ENOENT') {
- //file does not exist
- return done();
- }
- // other error
- return next(err)
- })
- });
- }))
- .on('error', callback)
- .pipe(through(function (obj, _, next) {
- if (!copied) {
- copied = true;
- }
- var pathName = obj.pathName;
- var pathStat = obj.pathStat;
- var outName = path.join(outDir, dealWith(pathName, opts));
- debug(`copy from: ${pathName}`)
- debug(`copy to: ${outName}`)
- copyFile(pathName, outName, pathStat, next)
- }))
- .on('error', callback)
- .on('finish', function () {
- if (config.error && !copied) {
- return callback(new Error('nothing coppied'));
- }
- callback();
- });
- }
|