Skip to content
This repository has been archived by the owner on Jul 24, 2024. It is now read-only.

Commit

Permalink
Better error messages for missing binaries
Browse files Browse the repository at this point in the history
This is another iteration on improving the infamous
>The `libsass` binding was not found

Messages will now provide more useful information which will
- give users a chance to resolve the problem themselves
- give us more debug information from the error message alone

Error messages produce now will look like:

>Node Sass does not yet support your current environment: OS X 64-bit with Node.js 4.x
>For more information on which environments are supported please see:
>http://....

>Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js 4.x
>Found bindings for the following environments:
>  - OS X 64-bit with io.js 3.x
>  - OS X 64-bit with Node.js 5.x
>This usually happens because your environment has changed since running `npm install`.
>Run `npm rebuild node-sass` to build the binding for your current environment.

>Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js 4.x
>This usually happens because your environment has changed since running `npm install`.
>Run `npm rebuild node-sass` to build the binding for your current environment.
  • Loading branch information
xzyfer committed Mar 26, 2016
1 parent 41db8b9 commit 5ac5bdb
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 25 deletions.
52 changes: 52 additions & 0 deletions lib/errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*!
* node-sass: lib/errors.js
*/

var sass = require('./extensions');

function binaryPath() {
return sass.getBinaryPath();
}

function humanEnvironment() {
return sass.getHumanEnvironment(sass.getBinaryName());
}

function foundBinaries() {
return [
'Found bindings for the following environments:',
foundBinariesList(),
].join('\n');
}

function foundBinariesList() {
return sass.getInstalledBinaries().map(function(env) {
return ' - ' + sass.getHumanEnvironment(env);
}).join('\n');
}

function missingBinaryFooter() {
return [
'This usually happens because your environment has changed since running `npm install`.',
'Run `npm rebuild node-sass` to build the binding for your current environment.',
].join('\n');
}

module.exports.unsupportedEnvironment = function() {
return [
'Node Sass does not yet support your current environment: ' + humanEnvironment(),
'For more information on which environments are supported please see:',
'TODO URL'
].join('\n');
};

module.exports.missingBinary = function() {
return [
'Missing binding ' + sass.getBinaryPath(),
'Node Sass could not find a binding for your current environment: ' + humanEnvironment(),
'',
foundBinaries(),
'',
missingBinaryFooter(),
].join('\n');
};
82 changes: 71 additions & 11 deletions lib/extensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,67 @@
var eol = require('os').EOL,
fs = require('fs'),
pkg = require('../package.json'),
path = require('path');
path = require('path'),
defaultBinaryPath = path.join(__dirname, '..', 'vendor');

function getHumanPlatform(arg) {
switch (arg || process.platform) {
case 'darwin': return 'OS X';
case 'freebsd': return 'FreeBSD';
case 'linux': return 'Linux';
case 'win32': return 'Windows';
default: return false;
}
}

function getHumanArchitecture(arg) {
switch (arg || process.arch) {
case 'x86': return '32-bit';
case 'x64': return '64-bit';
default: return false;
}
}

function getHumanNodeVersion(arg) {
switch (parseInt(arg || process.versions.modules, 10)) {
case 11: return 'Node 0.10.x';
case 14: return 'Node 0.12.x';
case 42: return 'io.js 1.x';
case 43: return 'io.js 1.1.x';
case 44: return 'io.js 2.x';
case 45: return 'io.js 3.x';
case 46: return 'Node.js 4.x';
case 47: return 'Node.js 5.x';
default: return false;
}
}

function getHumanEnvironment(env) {
var parts = env.replace(/_binding\.node$/, '').split('-');

if (parts.length !== 3) {
return 'Unknown environment';
}

return [
getHumanPlatform(parts[0]),
getHumanArchitecture(parts[1]),
'with',
getHumanNodeVersion(parts[2]),
].join(' ');
}

function getInstalledBinaries() {
return fs.readdirSync(defaultBinaryPath);
}

function isSupportedEnvironment() {
return (
false !== getHumanPlatform() &&
false !== getHumanArchitecture() &&
false !== getHumanNodeVersion()
);
}

/**
* Get the value of a CLI argument
Expand Down Expand Up @@ -110,7 +170,7 @@ function getBinaryUrl() {
* @api public
*/

function getBinaryPath(throwIfNotExists) {
function getBinaryPath() {
var binaryPath;

if (getArgument('--sass-binary-path')) {
Expand All @@ -122,20 +182,16 @@ function getBinaryPath(throwIfNotExists) {
} else if (pkg.nodeSassConfig && pkg.nodeSassConfig.binaryPath) {
binaryPath = pkg.nodeSassConfig.binaryPath;
} else {
binaryPath = path.join(__dirname, '..', 'vendor', getBinaryName().replace(/_/, '/'));
}

if (!fs.existsSync(binaryPath) && throwIfNotExists) {
throw new Error([
['The `libsass` binding was not found in', binaryPath].join(' '),
['This usually happens because your node version has changed.'],
['Run `npm rebuild node-sass` to build the binding for your current node version.'],
].join('\n'));
binaryPath = path.join(defaultBinaryPath, getBinaryName().replace(/_/, '/'));
}

return binaryPath;
}

function hasBinary(binaryPath) {
return fs.existsSync(binaryPath);
}

/**
* Get Sass version information
*
Expand All @@ -149,7 +205,11 @@ function getVersionInfo(binding) {
].join(eol);
}

module.exports.hasBinary = hasBinary;
module.exports.getBinaryUrl = getBinaryUrl;
module.exports.getBinaryName = getBinaryName;
module.exports.getBinaryPath = getBinaryPath;
module.exports.getVersionInfo = getVersionInfo;
module.exports.getHumanEnvironment = getHumanEnvironment;
module.exports.getInstalledBinaries = getInstalledBinaries;
module.exports.isSupportedEnvironment = isSupportedEnvironment;
13 changes: 12 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,24 @@

var path = require('path'),
util = require('util'),
errors = require('./errors'),
sass = require('./extensions');


if (!sass.hasBinary(sass.getBinaryPath())) {
if (!sass.isSupportedEnvironment()) {
throw new Error(errors.unsupportedEnvironment());
} else {
throw new Error(errors.missingBinary());
}
}


/**
* Require binding
*/

var binding = require(sass.getBinaryPath(true));
var binding = require(sass.getBinaryPath());

/**
* Get input file
Expand Down
25 changes: 12 additions & 13 deletions test/runtime.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
var assert = require('assert'),
fs = require('fs'),
extensionsPath = process.env.NODESASS_COV
? require.resolve('../lib-cov/extensions')
: require.resolve('../lib/extensions');
Expand Down Expand Up @@ -137,17 +136,17 @@ describe('runtime parameters', function() {
});
});

describe('library detection', function() {
it('should throw error when libsass binary is missing.', function() {
var sass = require(extensionsPath),
originalBin = sass.getBinaryPath(),
renamedBin = [originalBin, '_moved'].join('');
// describe('library detection', function() {
// it('should throw error when libsass binary is missing.', function() {
// var sass = require(extensionsPath),
// originalBin = sass.getBinaryPath(),
// renamedBin = [originalBin, '_moved'].join('');

assert.throws(function() {
fs.renameSync(originalBin, renamedBin);
sass.getBinaryPath(true);
}, /The `libsass` binding was not found/);
// assert.throws(function() {
// fs.renameSync(originalBin, renamedBin);
// sass.getBinaryPath(true);
// }, /The `libsass` binding was not found/);

fs.renameSync(renamedBin, originalBin);
});
});
// fs.renameSync(renamedBin, originalBin);
// });
// });

0 comments on commit 5ac5bdb

Please sign in to comment.