diff --git a/README.md b/README.md index dcd5e78a..a5b61e8d 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,14 @@ Type: `Number` Default: The process mode. +##### `options.relative` + +Whether or not the symlink should be relative or absolute. + +Type: `Boolean` + +Default: `false`. + ##### other Any through2-related options are documented in [through2]. diff --git a/lib/symlink/index.js b/lib/symlink/index.js index 94248ef8..e2b0f6fa 100644 --- a/lib/symlink/index.js +++ b/lib/symlink/index.js @@ -2,16 +2,34 @@ var through2 = require('through2'); var fs = require('graceful-fs'); +var path = require('path'); +var valueOrFunction = require('value-or-function'); + var prepareWrite = require('../prepare-write'); +var defaultValue = require('../default-value'); + +var boolean = valueOrFunction.boolean; function symlink(outFolder, opt) { + if (!opt) { + opt = {}; + } + function linkFile(file, enc, cb) { var srcPath = file.path; var symType = (file.isDirectory() ? 'dir' : 'file'); + var isRelative = defaultValue(false, boolean(opt.relative, file)); + prepareWrite(outFolder, file, opt, function(err) { if (err) { return cb(err); } + + // This is done inside prepareWrite to use the adjusted file.base property + if (isRelative) { + srcPath = path.relative(file.base, srcPath); + } + fs.symlink(srcPath, file.path, symType, function(err) { if (err && err.code !== 'EEXIST') { return cb(err); diff --git a/test/symlink.js b/test/symlink.js index 740bdd91..50ea5843 100644 --- a/test/symlink.js +++ b/test/symlink.js @@ -13,6 +13,7 @@ var del = require('del'); var bufEqual = require('buffer-equal'); var through = require('through2'); +var assign = require('object-assign'); var File = require('vinyl'); var should = require('should'); @@ -223,6 +224,46 @@ describe('symlink stream', function() { stream.end(); }); + it('should write buffer files to the right folder relatively', function(done) { + var inputPath = path.join(__dirname, './fixtures/test.coffee'); + var inputBase = path.join(__dirname, './fixtures/'); + var expectedPath = path.join(__dirname, './out-fixtures/test.coffee'); + var expectedContents = fs.readFileSync(inputPath); + var expectedBase = path.join(__dirname, './out-fixtures'); + var expectedMode = parseInt('677', 8) & ~process.umask(); + + var expectedFile = new File({ + base: inputBase, + cwd: __dirname, + path: inputPath, + contents: expectedContents, + stat: { + mode: expectedMode, + }, + }); + + var buffered = []; + + var onEnd = function() { + buffered.length.should.equal(1); + buffered[0].should.equal(expectedFile); + buffered[0].cwd.should.equal(__dirname, 'cwd should have changed'); + buffered[0].base.should.equal(expectedBase, 'base should have changed'); + buffered[0].path.should.equal(expectedPath, 'path should have changed'); + fs.existsSync(expectedPath).should.equal(true); + bufEqual(fs.readFileSync(expectedPath), expectedContents).should.equal(true); + fs.readlinkSync(expectedPath).should.equal(path.join('..', 'fixtures', 'test.coffee')); + done(); + }; + + var stream = vfs.symlink('./out-fixtures/', assign({ cwd: __dirname }, { relative: true })); + + var bufferStream = through.obj(dataWrap(buffered.push.bind(buffered)), onEnd); + stream.pipe(bufferStream); + stream.write(expectedFile); + stream.end(); + }); + it('should write streaming files to the right folder', function(done) { var inputPath = path.join(__dirname, './fixtures/test.coffee'); var inputBase = path.join(__dirname, './fixtures/'); @@ -310,6 +351,48 @@ describe('symlink stream', function() { stream.end(); }); + it('should write directories to the right folder relatively', function(done) { + var inputPath = path.join(__dirname, './fixtures/wow'); + var inputBase = path.join(__dirname, './fixtures/'); + var expectedPath = path.join(__dirname, './out-fixtures/wow'); + var expectedBase = path.join(__dirname, './out-fixtures'); + var expectedMode = parseInt('677', 8) & ~process.umask(); + + var expectedFile = new File({ + base: inputBase, + cwd: __dirname, + path: inputPath, + contents: null, + stat: { + isDirectory: function() { + return true; + }, + mode: expectedMode, + }, + }); + + var buffered = []; + + var onEnd = function() { + buffered.length.should.equal(1); + buffered[0].should.equal(expectedFile); + buffered[0].cwd.should.equal(__dirname, 'cwd should have changed'); + buffered[0].base.should.equal(expectedBase, 'base should have changed'); + buffered[0].path.should.equal(expectedPath, 'path should have changed'); + fs.readlinkSync(expectedPath).should.equal(path.join('..', 'fixtures', 'wow')); + fs.lstatSync(expectedPath).isDirectory().should.equal(false); + fs.statSync(expectedPath).isDirectory().should.equal(true); + done(); + }; + + var stream = vfs.symlink('./out-fixtures/', assign({ cwd: __dirname }, { relative: true })); + + var bufferStream = through.obj(dataWrap(buffered.push.bind(buffered)), onEnd); + stream.pipe(bufferStream); + stream.write(expectedFile); + stream.end(); + }); + it('should use different modes for files and directories', function(done) { if (isWindows) { console.log('Changing the mode of a file is not supported by node.js in Windows.');