Skip to content

Commit

Permalink
New: Add relative symlink support (closes #177) (#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
perrin4869 authored and phated committed Nov 30, 2017
1 parent 8eb33dc commit ec182e5
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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].
Expand Down
18 changes: 18 additions & 0 deletions lib/symlink/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
83 changes: 83 additions & 0 deletions test/symlink.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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/');
Expand Down Expand Up @@ -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.');
Expand Down

0 comments on commit ec182e5

Please sign in to comment.