gulp-symlink
Advanced tools
Comparing version
@@ -9,7 +9,6 @@ /* jshint node:true */ | ||
mocha = require('gulp-mocha'), | ||
jshint = require('gulp-jshint'), | ||
stylish = require('jshint-stylish'); | ||
jshint = require('gulp-jshint'); | ||
gulp.task('lint', function () { | ||
gulp.src('*.js') | ||
gulp.src(['*.js', 'test/**/*.js']) | ||
.pipe(jshint()) | ||
@@ -16,0 +15,0 @@ .pipe(jshint.reporter('jshint-stylish')) |
201
index.js
@@ -10,84 +10,169 @@ /* jshint node:true */ | ||
fs = require('fs'), | ||
async = require('async'), | ||
PluginError = gutil.PluginError, | ||
File = gutil.File, | ||
debug; | ||
PLUGIN_NAME = 'gulp-symlink'; | ||
var PLUGIN_NAME = 'gulp-symlink'; | ||
function localPath(absolutePath) { | ||
var cwd = process.cwd(); | ||
return absolutePath.indexOf(cwd) === 0 ? absolutePath.substr(cwd.length + 1) : absolutePath; | ||
} | ||
/** | ||
* Wrapper to log when debug === true | ||
* it's basically a console.log | ||
*/ | ||
var log = function() { | ||
if(debug === true) { | ||
console.log.apply(console, [].slice.call(arguments)); | ||
return console.log; | ||
} else { | ||
return function() { }; | ||
} | ||
var symlinker = function(symlink, resolver) { | ||
return through.obj(function(file, encoding, cb) { | ||
var self = this, | ||
sym = null; | ||
}; | ||
if (typeof symlink === 'undefined') { | ||
this.emit('error', new gutil.PluginError(PLUGIN_NAME, 'An output destination is required.')); | ||
return cb(); | ||
} | ||
/** | ||
* Error wrapper - this is called in the through context | ||
* @param {Error} error The error | ||
* @return {Function} cb The through callback | ||
*/ | ||
var errored = function(error, cb) { | ||
this.emit('error', new PluginError(PLUGIN_NAME, error)); | ||
//Push the file so that the stream is piped to the next task even if it has errored | ||
//might be discussed | ||
this.push(this.source); | ||
return cb(); | ||
}; | ||
var out = function(file) { | ||
return (typeof symlink === 'string') ? symlink : symlink(file); | ||
}; | ||
var symlinker = function(destination, resolver, options) { | ||
var destination = resolver.call(this, process.cwd(), out(file)); | ||
if(typeof resolver === 'object') { | ||
options = resolver; | ||
resolver = 'relative'; | ||
} | ||
// Check whether the destination is a directory | ||
if (path.extname(out(file)) === '') { | ||
sym = path.join(destination, path.basename(file.path)); | ||
} else { | ||
sym = destination; | ||
destination = destination.replace(path.basename(destination), ''); | ||
} | ||
options = typeof options === 'object' ? options : {}; | ||
options.force = options.force === undefined ? false : options.force; | ||
var source = resolver.call(this, destination, file.path); | ||
//Handling array of destinations, this test is because "instance of" isn't safe | ||
if( Object.prototype.toString.call( destination ) === '[object Array]' ) { | ||
//copy array because we'll shift values | ||
var destinations = destination.slice(); | ||
} | ||
var finish = function(err) { | ||
if (err && err.code !== 'EEXIST') { | ||
self.emit('error', new gutil.PluginError(PLUGIN_NAME, err)); | ||
return cb(); | ||
return through.obj(function(source, encoding, callback) { | ||
var self = this, symlink; | ||
this.source = source; //error binding | ||
//else if we've got an array from before take the next element as a destination path | ||
symlink = destinations !== undefined ? destinations.shift() : symlink; | ||
//if destination is a function pass the source to it | ||
if(symlink === undefined) { | ||
symlink = typeof destination === 'function' ? destination(source) : destination; | ||
} | ||
//if symlink is still undefined there is a problem! | ||
if (symlink === undefined) { | ||
return errored.call(self, 'An output destination is required.', callback); | ||
} | ||
// Convert the destination path to a new vinyl instance | ||
symlink = symlink instanceof File ? symlink : new File({ path: symlink }); | ||
log('Before resolving')('Source: %s – dest: %s', source.path, symlink.path); | ||
symlink.directory = path.dirname(symlink.path); //this is the parent directory of the symlink | ||
// Resolve the path to the symlink | ||
if(resolver === 'relative' || options.relative === true) { | ||
source.resolved = path.relative(symlink.directory, source.path); | ||
} else { | ||
//resolve the absolute path from the source. It need to be from the current working directory to handle relative sources | ||
source.resolved = path.resolve(source.cwd, source.path); | ||
} | ||
log('After resolving')(source.resolved + ' in ' + symlink.path); | ||
fs.exists(symlink.path, function(exists) { | ||
//No force option, we can't override! | ||
if(exists && !options.force) { | ||
return errored.call(self, 'Destination file exists ('+destination+') - use force option to replace', callback); | ||
} else { | ||
async.waterfall([ | ||
function(next){ | ||
//remove destination if it exists already | ||
if(exists && options.force === true) { | ||
fs.unlink(symlink.path, function(err) { | ||
if(err) { | ||
return errored.call(self, err, callback); | ||
} | ||
next(); | ||
}); | ||
} else { | ||
next(); | ||
} | ||
self.push(file); | ||
if (symlinker.prototype.debug === false) { | ||
gutil.log(gutil.colors.magenta(localPath(file.path)), 'symlinked to', gutil.colors.magenta(localPath(sym))); | ||
}, | ||
//checking if the parent directory exists | ||
function(next) { | ||
mkdirp(symlink.directory, function(err) { | ||
//ignoring directory err if it exists | ||
if(err && err.code !== 'EEXIST') { | ||
return errored.call(self, err, callback); | ||
} | ||
next(); | ||
}); | ||
} | ||
], function () { | ||
//this is a windows check as specified in http://nodejs.org/api/fs.html#fs_fs_symlink_srcpath_dstpath_type_callback | ||
fs.stat(source.path, function(err, stat) { | ||
if(err) { | ||
return errored.call(self, err, callback); | ||
} | ||
cb(); | ||
}; | ||
fs.symlink(source, sym, function(err) { | ||
// Most likely there's no directory there... | ||
if (err && err.code === 'ENOENT') { | ||
// Recursively make directories in case we want a nested symlink | ||
return mkdirp(destination, function(err) { | ||
if (err) { | ||
self.emit('error', new gutil.PluginError(PLUGIN_NAME, err), file); | ||
return cb(); | ||
} | ||
fs.symlink(source, sym, finish); | ||
}); | ||
} | ||
finish(err); | ||
source.stat = stat; | ||
fs.symlink(source.resolved, symlink.path, source.stat.isDirectory() ? 'dir' : 'file', function(err) { | ||
if(err) { | ||
return errored.call(self, err, callback); | ||
} else { | ||
gutil.log(PLUGIN_NAME + ':' + gutil.colors.magenta(source.path), 'symlinked to', gutil.colors.magenta(symlink.path)); | ||
self.push(source); | ||
return callback(); | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
}); | ||
}; | ||
var relativesymlinker = function(symlink) { | ||
return symlinker(symlink, path.relative); | ||
}); | ||
}; | ||
var absolutesymlinker = function(symlink) { | ||
return symlinker(symlink, path.resolve); | ||
var relativesymlinker = function(symlink, options) { | ||
return symlinker(symlink, 'relative', options); | ||
}; | ||
var _setDebug = function(value) { | ||
symlinker.prototype.debug = value; | ||
var absolutesymlinker = function(symlink, options) { | ||
return symlinker(symlink, 'absolute', options); | ||
}; | ||
_setDebug(false); | ||
// Expose main functionality under relative, for convenience | ||
module.exports = relativesymlinker; | ||
module.exports.relative = relativesymlinker; | ||
module.exports.absolute = absolutesymlinker; | ||
module.exports._setDebug = _setDebug; | ||
module.exports._setDebug = function(value) { | ||
debug = value; | ||
}; |
{ | ||
"name": "gulp-symlink", | ||
"version": "1.1.0", | ||
"version": "2.0.0", | ||
"description": "Create symlinks during your gulp build.", | ||
@@ -24,17 +24,18 @@ "license": "MIT", | ||
"dependencies": { | ||
"gulp-util": "~2.2.14", | ||
"mkdirp": "^0.4.0", | ||
"through2": "^0.4.1" | ||
"gulp-util": "~3.0.0", | ||
"mkdirp": "~0.5.0", | ||
"through2": "~0.5.1", | ||
"async": "~0.9.0" | ||
}, | ||
"devDependencies": { | ||
"chai": "~1.9.0", | ||
"chai": "~1.9.1", | ||
"clear": "0.0.1", | ||
"gulp": "~3.5.2", | ||
"gulp-jshint": "~1.4.0", | ||
"gulp-mocha": "~0.4.1", | ||
"gulp-mocha": "~0.5.1", | ||
"jshint-stylish": "~0.1.5", | ||
"mocha": "~1.17.1", | ||
"rimraf": "^2.2.6" | ||
"mocha": "~1.20.1", | ||
"gulp-jshint": "~1.7.1", | ||
"gulp": "~3.8.6", | ||
"rimraf": "~2.2.8" | ||
}, | ||
"main": "index.js" | ||
} |
@@ -5,4 +5,2 @@ # [gulp](https://github.com/gulpjs/gulp)-symlink [](https://travis-ci.org/ben-eb/gulp-symlink) [](http://badge.fury.io/js/gulp-symlink) [](https://gemnasium.com/ben-eb/gulp-symlink) | ||
**NOTE: Breaking changes are introduced in 1.0.0. gulp-symlink has been rewritten with a simpler API, that takes the output directory and renamed file as a single parameter. Existing gulpfiles using the old API will break if this module is substituted for the 0.4.x releases. Please take care to read the new API docs for migrating over from older versions. Thank you.** | ||
## Installation | ||
@@ -19,9 +17,8 @@ | ||
```js | ||
var gulp = require('gulp'); | ||
var symlink = require('gulp-symlink'); | ||
gulp.task('default', function() { | ||
return gulp.src('assets/some-large-video.mp4') | ||
.pipe(symlink('build/videos')) // Write to the destination folder | ||
.pipe(symlink('build/videos/renamed-video.mp4')) // Write a renamed symlink to the destination folder | ||
return gulp.src('assets/some-large-video.mp4') | ||
.pipe(symlink('build/videos')) // Write to the destination folder | ||
.pipe(symlink('build/videos/renamed-video.mp4')) // Write a renamed symlink to the destination folder | ||
}); | ||
@@ -32,21 +29,41 @@ ``` | ||
### symlink(symlinkpath) or symlink.relative(symlinkpath) | ||
### symlink(path, [options]), symlink.relative(path, [options]) or symlink.absolute(path, [options]) | ||
Pass a `string` or a `function` to create the symlink. The function is passed the [vinyl](https://github.com/wearefractal/vinyl) object, so you can use `file.base`, `file.path` etc. Just make sure you return a string that is the location and or filename of the new symlink. For example: | ||
Pass a `string` or a `function` to create the symlink. | ||
The function is passed the [vinyl](https://github.com/wearefractal/vinyl) object, so you can use `file.base`, `file.path` etc. | ||
For example: | ||
```js | ||
var path = require('path'); | ||
gulp.task('symlink', function() { | ||
return gulp.src('assets/some-large-video.mp4') | ||
.pipe(symlink(function(file) { | ||
return path.join(file.base, 'build', file.relative.replace('some-large', '')); | ||
})); | ||
return gulp.src('assets/some-large-video.mp4') | ||
.pipe(symlink(function(file) { | ||
//here we return a path as string | ||
return path.join(file.base, 'build', file.relative.replace('some-large', '')); | ||
})); | ||
}); | ||
gulp.task('symlink-vinyl', function() { | ||
return gulp.src('assets/some-large-video.mp4') | ||
.pipe(symlink.absolute(function(file) { | ||
//here we return a Vinyl instance | ||
return new gutil.File({ | ||
path: 'build/videos/video.mp4', | ||
cwd: process.cwd() | ||
}, {force: true}); | ||
})); | ||
}) | ||
``` | ||
The string options work in the same way. If you pass a string like 'build/videos', the symlink will be created in that directory. If you pass 'build/videos/video.mp4', the symlink will also be renamed. | ||
The function will be called as many times as there are sources. | ||
### symlink.absolute(symlinkpath) | ||
You might also want to give an array of destination paths: | ||
The exact same as `symlink.relative` except this will create an *absolute symlink* instead. | ||
```js | ||
gulp.task('symlink', function() { | ||
return gulp.src('modules/assets/', 'modules/client/') | ||
.pipe(symlink(['./assets', './client'])); | ||
}); | ||
``` | ||
The default `symlink` performs a relative link. If you want an *absolute symlink* use `symlink.absolute` instead. |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
17540
42%12
20%327
59.51%67
34%4
33.33%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated
Updated