var fs = require('./fs'); var path = require('path'); var Q = require('q'); var mkdirp = require('mkdirp'); var createError = require('./createError'); var isWin = process.platform === 'win32'; function createLink(src, dst, type) { var dstDir = path.dirname(dst); // Create directory return ( Q.nfcall(mkdirp, dstDir) // Check if source exists .then(function() { return Q.nfcall(fs.stat, src).fail(function(error) { if (error.code === 'ENOENT') { throw createError( 'Failed to create link to ' + path.basename(src), 'ENOENT', { details: src + ' does not exist or points to a non-existent file' } ); } throw error; }); }) // Create symlink .then(function(stat) { type = type || (stat.isDirectory() ? 'dir' : 'file'); return Q.nfcall(fs.symlink, src, dst, type).fail(function(err) { if (!isWin || err.code !== 'EPERM') { throw err; } // Try with type "junction" on Windows // Junctions behave equally to true symlinks and can be created in // non elevated terminal (well, not always..) return Q.nfcall(fs.symlink, src, dst, 'junction').fail( function(err) { throw createError( 'Unable to create link to ' + path.basename(src), err.code, { details: err.message.trim() + '\n\nTry running this command in an elevated terminal (run as root/administrator).' } ); } ); }); }) ); } module.exports = createLink;