Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

grunt-sync

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

grunt-sync - npm Package Compare versions

Comparing version 0.2.2 to 0.2.3

97

package.json
{
"name": "grunt-sync",
"description": "Task to synchronize two directories. Similar to grunt-copy but updates only files that have been changed.",
"version": "0.2.2",
"homepage": "https://github.com/tomusdrw/grunt-sync.git",
"author": {
"name": "Tomasz Drwiega",
"email": "tomusdrw@blacksoft.eu",
"url": "http://blacksoft.eu"
},
"repository": {
"type": "git",
"url": "git://github.com/tomusdrw/grunt-sync.git"
},
"bugs": {
"url": "https://github.com/tomusdrw/grunt-sync/issues"
},
"licences": [{
"type": "MIT",
"url": "http://opensource.org/licenses/MIT"
}],
"main": "Gruntfile.js",
"readmeFilename": "readme.md",
"engines": {
"node": ">=0.8.0"
},
"scripts": {
"test": "mocha"
},
"dependencies": {
"glob": "^4.0.5",
"promised-io": "0.3.3"
},
"devDependencies": {
"chai": "1.4.2",
"grunt": "0.4.x",
"grunt-complexity": "^0.1.51",
"grunt-contrib-jshint": "0.1.x",
"grunt-simple-mocha": "0.3.x",
"mocha": "~1.8.1",
"time-grunt": "^0.4.0"
},
"keywords": [
"gruntplugin",
"sync",
"synchronize",
"copy"
]
"name": "grunt-sync",
"description": "Task to synchronize two directories. Similar to grunt-copy but updates only files that have been changed.",
"version": "0.2.3",
"homepage": "https://github.com/tomusdrw/grunt-sync.git",
"author": {
"name": "Tomasz Drwiega",
"email": "tomusdrw@blacksoft.eu",
"url": "http://blacksoft.eu"
},
"repository": {
"type": "git",
"url": "git://github.com/tomusdrw/grunt-sync.git"
},
"bugs": {
"url": "https://github.com/tomusdrw/grunt-sync/issues"
},
"licences": [
{
"type": "MIT",
"url": "http://opensource.org/licenses/MIT"
}
],
"main": "Gruntfile.js",
"readmeFilename": "readme.md",
"engines": {
"node": ">=0.8.0"
},
"scripts": {
"test": "mocha"
},
"dependencies": {
"glob": "^4.0.5",
"lodash": "^2.4.1",
"promised-io": "0.3.3"
},
"devDependencies": {
"chai": "1.4.2",
"grunt": "0.4.x",
"grunt-complexity": "^0.1.51",
"grunt-contrib-jshint": "0.1.x",
"grunt-simple-mocha": "0.3.x",
"mocha": "~1.8.1",
"time-grunt": "^0.4.0"
},
"keywords": [
"gruntplugin",
"sync",
"synchronize",
"copy"
]
}
{
"main": {
"files": [{
"src": ["**"],
"dest": "bin/to/",
"expand": true,
"cwd": "bin/from"
}],
"ignoreInDest": ["t", "*.js"],
"updateAndDelete": true,
"verbose": true,
"pretend": true
},
"rename": {
"src": "bin/somefile.txt",
"dest": "bin/somefile2.txt"
},
"windows": {
"files": [
{ "src": ["www\\**\\*.*", "!**\\*.ts"], "dest": "cordova\\"}],
"verbose": true,
"pretend": false,
"updateAndDelete": true
}
"main": {
"files": [{
"src": ["**"],
"dest": "bin/to/",
"expand": true,
"cwd": "bin/from/"
}],
"verbose": true,
"pretend": true
},
"rename": {
"src": "bin/somefile.txt",
"dest": "bin/somefile2.txt"
},
"windows": {
"files": [{
"src": ["www\\**\\*.*", "!**\\*.ts"],
"dest": "cordova\\"
}],
"verbose": true,
"pretend": false,
"updateAndDelete": true
},
"no26": {
"files": [{
"cwd": "bin/p2/icons",
"expand": true,
"src": "**/*",
"dest": "bin/p2/build/imgs/icons"
}, {
"cwd": "bin/p2/src/js",
"expand": true,
"src": "**/*",
"dest": "bin/p2/build/js"
}, {
"expand": true,
"src": "bin/p2/index.html",
"dest": "bin/p2/build"
}],
"verbose": true,
"updateAndDelete": true
}
}
var fs = require('promised-io/fs'),
promise = require('promised-io/promise'),
path = require('path'),
glob = require('glob'),
util = require('util');
promise = require('promised-io/promise'),
path = require('path'),
glob = require('glob'),
util = require('util'),
_ = require('lodash');
module.exports = function(grunt) {
var tryCopy = function(src, dest) {
try {
grunt.file.copy(src, dest);
} catch (e) {
grunt.log.warn('Cannot copy to ' + dest.red);
}
};
var tryCopy = function(src, dest) {
try {
grunt.file.copy(src, dest);
} catch (e) {
grunt.log.warn('Cannot copy to ' + dest.red);
}
};
var tryMkdir = function(dest) {
try {
grunt.file.mkdir(dest);
} catch (e) {
grunt.log.warn('Cannot create directory ' + dest.red);
}
};
var tryMkdir = function(dest) {
try {
grunt.file.mkdir(dest);
} catch (e) {
grunt.log.warn('Cannot create directory ' + dest.red);
}
};
var overwriteDest = function(src, dest) {
try {
grunt.file['delete'](dest);
grunt.file.copy(src, dest);
} catch (e) {
grunt.log.warn('Cannot overwrite ' + dest.red);
}
var overwriteDest = function(src, dest) {
try {
grunt.file['delete'](dest);
grunt.file.copy(src, dest);
} catch (e) {
grunt.log.warn('Cannot overwrite ' + dest.red);
}
};
var processPair = function(justPretend, logger, src, dest) {
var doOrPretend = function(operation) {
if (justPretend) {
return;
}
operation();
};
var overwriteOrUpdate = function(isSrcDirectory, typeDiffers, srcStat, destStat) {
var processPair = function(justPretend, logger, src, dest) {
var doOrPretend = function(operation) {
if (justPretend) {
return;
}
operation();
};
// If types differ we have to overwrite destination.
if (typeDiffers) {
logger.writeln('Overwriting ' + dest.cyan + ' because type differs.');
var overwriteOrUpdate = function(isSrcDirectory, typeDiffers, srcStat, destStat) {
doOrPretend(function() {
overwriteDest(src, dest);
});
return;
}
// If types differ we have to overwrite destination.
if (typeDiffers) {
logger.writeln('Overwriting ' + dest.cyan + ' because type differs.');
// we can now compare modification dates of files
if (isSrcDirectory || srcStat.mtime.getTime() <= destStat.mtime.getTime()) {
return;
}
doOrPretend(function() {
overwriteDest(src, dest);
});
return;
}
logger.writeln('Updating file ' + dest.cyan);
doOrPretend(function() {
// and just update destination
tryCopy(src, dest);
});
};
// we can now compare modification dates of files
if (isSrcDirectory || srcStat.mtime.getTime() <= destStat.mtime.getTime()) {
return;
}
//stat destination file
return promise.all([fs.stat(src), fs.stat(dest)]).then(function(result) {
var srcStat = result[0],
destStat = result[1];
logger.writeln('Updating file ' + dest.cyan);
doOrPretend(function() {
// and just update destination
tryCopy(src, dest);
});
};
var isSrcDirectory = srcStat.isDirectory();
var typeDiffers = isSrcDirectory !== destStat.isDirectory();
//stat destination file
return promise.all([fs.stat(src), fs.stat(dest)]).then(function(result) {
var srcStat = result[0],
destStat = result[1];
overwriteOrUpdate(isSrcDirectory, typeDiffers, srcStat, destStat);
}, function() {
// we got an error which means that destination file does not exist
// so make a copy
if (grunt.file.isDir(src)) {
logger.writeln('Creating ' + dest.cyan);
var isSrcDirectory = srcStat.isDirectory();
var typeDiffers = isSrcDirectory !== destStat.isDirectory();
doOrPretend(function() {
tryMkdir(dest);
});
} else {
logger.writeln('Copying ' + src.cyan + ' -> ' + dest.cyan);
overwriteOrUpdate(isSrcDirectory, typeDiffers, srcStat, destStat);
}, function() {
// we got an error which means that destination file does not exist
// so make a copy
if (grunt.file.isDir(src)) {
logger.writeln('Creating ' + dest.cyan);
doOrPretend(function() {
tryCopy(src, dest);
});
}
});
};
doOrPretend(function() {
tryMkdir(dest);
});
} else {
logger.writeln('Copying ' + src.cyan + ' -> ' + dest.cyan);
var removePaths = function(justPretend, logger, paths) {
doOrPretend(function() {
tryCopy(src, dest);
});
}
return promise.all(paths.map(function(file) {
return fs.stat(file).then(function(stat) {
return {
file: file,
isDirectory: stat.isDirectory()
};
});
})).then(function(stats) {
var paths = splitFilesAndDirs(stats);
// First we need to process files
return promise.all(paths.files.map(function(filePath) {
logger.writeln('Unlinking ' + filePath.cyan + ' because it was removed from src.');
if (justPretend) {
return;
}
return fs.unlink(filePath);
})).then(function() {
// Then process directories in ascending order
var sortedDirs = paths.dirs.sort(function(a, b) {
return b.length - a.length;
});
};
var removePaths = function(justPretend, logger, paths) {
return promise.all(sortedDirs.map(function(dir) {
logger.writeln('Removing dir ' + dir.cyan + ' because not longer in src.');
if (justPretend) {
return;
}
return fs.rmdir(dir);
}));
});
});
return promise.all(paths.map(function(file) {
return fs.stat(file).then(function(stat) {
return {
file: file,
isDirectory: stat.isDirectory()
};
});
})).then(function(stats) {
var paths = splitFilesAndDirs(stats);
};
// First we need to process files
return promise.all(paths.files.map(function(filePath) {
logger.writeln('Unlinking ' + filePath.cyan + ' because it was removed from src.');
var splitFilesAndDirs = function(stats) {
return stats.reduce(function(memo, stat) {
if (stat.isDirectory) {
memo.dirs.push(stat.file);
} else {
memo.files.push(stat.file);
}
return memo;
}, {
files: [],
dirs: []
});
};
if (justPretend) {
return;
}
return fs.unlink(filePath);
})).then(function() {
// Then process directories in ascending order
var sortedDirs = paths.dirs.sort(function(a, b) {
return b.length - a.length;
});
var fastArrayDiff = function(from, diff) {
diff.map(function(v) {
from[from.indexOf(v)] = undefined;
});
return from.filter(function(v) {
return v;
});
};
return promise.all(sortedDirs.map(function(dir) {
logger.writeln('Removing dir ' + dir.cyan + ' because not longer in src.');
if (justPretend) {
return;
}
return fs.rmdir(dir);
}));
});
});
var convertPathsToSystemSpecific = function(paths) {
return paths.map(function(filePath) {
return path.join.apply(path, filePath.split('/'));
});
};
};
var addDirectoriesPaths = function(arr, dest) {
var f = dest.split(path.sep);
var i, p;
p = f[0];
var splitFilesAndDirs = function(stats) {
return stats.reduce(function(memo, stat) {
if (stat.isDirectory) {
memo.dirs.push(stat.file);
} else {
memo.files.push(stat.file);
}
return memo;
}, {
files: [],
dirs: []
});
};
for (i = 1; i < f.length - 1; ++i) {
p += path.sep + f[i];
if (arr.indexOf(p) === -1) {
arr.push(p);
}
}
};
var fastArrayDiff = function(from, diff) {
diff.map(function(v) {
from[from.indexOf(v)] = undefined;
});
return from.filter(function(v) {
return v;
});
};
grunt.registerMultiTask('sync', 'Synchronize content of two directories.', function() {
var done = this.async(),
logger = grunt[this.data.verbose ? 'log' : 'verbose'],
updateOnly = !this.data.updateAndDelete,
justPretend = !!this.data.pretend,
ignoredPatterns = this.data.ignoreInDest,
expandedPaths = {};
var convertPathsToSystemSpecific = function(paths) {
return paths.map(function(filePath) {
return path.join.apply(path, filePath.split('/'));
});
};
var addDirectoriesPaths = function(arr, dest) {
var f = dest.split(path.sep);
var i, p;
p = f[0];
for (i=1; i<f.length - 1; ++i) {
p += path.sep + f[i];
if (arr.indexOf(p) === -1) {
arr.push(p);
}
}
var getExpandedPaths = function(origDest) {
if (!expandedPaths[origDest]) {
// Always include destination as processed.
expandedPaths[origDest] = [origDest.replace(new RegExp("\\" + path.sep + "$"), '')];
return expandedPaths[origDest];
}
return expandedPaths[origDest];
};
grunt.registerMultiTask('sync', 'Synchronize content of two directories.', function() {
var done = this.async(),
logger = grunt[this.data.verbose ? 'log' : 'verbose'],
updateOnly = !this.data.updateAndDelete,
justPretend = !!this.data.pretend,
ignoredPatterns = this.data.ignoreInDest,
expandedPaths = {};
promise.all(this.files.map(function(fileDef) {
var isCompactForm = this.data.src && this.data.dest;
var cwd = fileDef.cwd ? fileDef.cwd : '.';
var isExpanded = fileDef.orig.expand;
var origDest = path.join(fileDef.orig.dest, '');
var processedDestinations = getExpandedPaths(origDest);
var getExpandedPaths = function(origDest) {
if (!expandedPaths[origDest]) {
// Always include destination as processed.
expandedPaths[origDest] = [origDest.replace(new RegExp("\\" + path.sep + "$"), '')];
return expandedPaths[origDest]
}
return expandedPaths[origDest];
};
return promise.all(fileDef.src.map(function(src) {
var dest;
// when using expanded mapping dest is the destination file
// not the destination folder
if (isExpanded || isCompactForm) {
dest = fileDef.dest;
} else {
dest = path.join(fileDef.dest, src);
}
if (!updateOnly) {
processedDestinations.push(dest);
// Make sure to add directory of file as well (handle cases when source has pattern for files only)
addDirectoriesPaths(processedDestinations, dest);
}
// Process pair
return processPair(justPretend, logger, path.join(cwd, src), dest);
}));
promise.all(this.files.map(function(fileDef) {
var isCompactForm = this.data.src && this.data.dest;
var cwd = fileDef.cwd ? fileDef.cwd : '.';
var isExpanded = fileDef.orig.expand;
var origDest = path.join(fileDef.orig.dest, '');
}, this)).then(function() {
if (updateOnly) {
return;
}
var processedDestinations = getExpandedPaths(origDest);
var getDestPaths = function(dest, pattern) {
var defer = new promise.Deferred();
glob(path.join(dest, pattern), {
dot: true
}, function(err, result) {
if (err) {
defer.reject(err);
return;
}
defer.resolve(result);
});
return defer.promise;
};
return promise.all(fileDef.src.map(function(src) {
var dest;
// when using expanded mapping dest is the destination file
// not the destination folder
if (isExpanded || isCompactForm) {
dest = fileDef.dest;
} else {
dest = path.join(fileDef.dest, src);
}
if (!updateOnly) {
processedDestinations.push(dest);
// Make sure to add directory of file as well (handle cases when source has pattern for files only)
addDirectoriesPaths(processedDestinations, dest);
}
// Process pair
return processPair(justPretend, logger, path.join(cwd, src), dest);
}));
var getIgnoredPaths = function(dest, ignore) {
var defer = new promise.Deferred();
if (!ignore) {
defer.resolve([]);
return defer.promise;
}
}, this)).then(function() {
if (updateOnly) {
return;
}
if (!util.isArray(ignore)) {
ignore = [ignore];
}
var getDestPaths = function(dest, pattern) {
var defer = new promise.Deferred();
glob(path.join(dest, pattern), {
dot: true
}, function(err, result) {
if (err) {
defer.reject(err);
return;
}
defer.resolve(result);
});
return defer.promise;
};
var getIgnoredPaths = function(dest, ignore) {
var defer = new promise.Deferred();
if (!ignore) {
defer.resolve([]);
return defer.promise;
}
promise.all(ignore.map(function(pattern) {
return getDestPaths(dest, pattern);
})).then(function(results) {
var flat = results.reduce(function(memo, a) {
return memo.concat(a);
}, []);
defer.resolve(flat);
}, function(err) {
defer.reject(err);
});
if (!util.isArray(ignore)) {
ignore = [ignore]
}
return defer.promise;
};
promise.all(ignore.map(function(pattern) {
return getDestPaths(dest, pattern);
})).then(function(results) {
var flat = results.reduce(function(memo, a) {
return memo.concat(a);
}, []);
defer.resolve(flat);
}, function(err) {
defer.reject(err);
});
// Second pass
return promise.all(Object.keys(expandedPaths).map(function(dest) {
var processedDestinations = convertPathsToSystemSpecific(expandedPaths[dest]);
return defer.promise;
};
// We have to do second pass to remove objects from dest
var destPaths = getDestPaths(dest, '**');
// Second pass
return promise.all(Object.keys(expandedPaths).map(function(dest) {
var processedDestinations = convertPathsToSystemSpecific(expandedPaths[dest]);
// Check if we have any ignore patterns
var ignoredPaths = getIgnoredPaths(dest, ignoredPatterns);
// We have to do second pass to remove objects from dest
var destPaths = getDestPaths(dest, '**');
return promise.all([destPaths, ignoredPaths, processedDestinations]);
})).then(function(result) {
var files = result.map(function(destAndIgnored) {
var paths = convertPathsToSystemSpecific(destAndIgnored[0]);
var ignoredPaths = convertPathsToSystemSpecific(destAndIgnored[1]);
// Check if we have any ignore patterns
var ignoredPaths = getIgnoredPaths(dest, ignoredPatterns);
return [paths, ignoredPaths, destAndIgnored[2]];
}).reduce(function(memo, destAndIgnored) {
return memo.map(function(val, key) {
return val.concat(destAndIgnored[key]);
});
}, [[], [], []]);
// TODO Find some faster way to ensure uniqueness here
var paths = _.uniq(files[0]);
var ignoredPaths = _.uniq(files[1]);
var processedDestinations = _.uniq(files[2]);
return promise.all([destPaths, ignoredPaths]).then(function(result) {
var paths = convertPathsToSystemSpecific(result[0]);
var ignoredPaths = convertPathsToSystemSpecific(result[1]);
// Calculate diff
var toRemove = fastArrayDiff(paths, processedDestinations);
// And filter also ignored paths
toRemove = fastArrayDiff(toRemove, ignoredPaths);
return removePaths(justPretend, logger, toRemove);
});
}));
}).then(done);
});
// Calculate diff
var toRemove = fastArrayDiff(paths, processedDestinations);
// And filter also ignored paths
toRemove = fastArrayDiff(toRemove, ignoredPaths);
return removePaths(justPretend, logger, toRemove);
});
}).then(done);
});
};

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc