Commit 2220ba96 by Adeel

Build: Centralises binary naming conventions.

* Delivers binary name, paths and download URL
  from lib/extensions.js.

* Allows user to set binary name as environment
  variable with `SASS_BINARY_NAME`.
  * Note: this will supersede default name.
* Allows user to set binary name as in package
  file `"nodeSassConfig": { "binary-name": "" }`.
  * Note: this will supersede default name and
    `SASS_BINARY_NAME` environment variable.
* Allows user to set binary name as parameter to
  invoke any node-sass script with
  `--binary-name` flag.
  * Note: this will supersede default name, name
    defined in package `nodeSassConfig` as well
    as the `SASS_BINARY_NAME` environment
    variable.

* This binary name will be used to construct the:
  * Binary path.
  * Binary download URL.
  * Upload URL.

* Allows user to set binary path as environment
  variable with `SASS_BINARY_PATH`.
  * Note: this will supersede default path.
* Allows user to set binary name as in package
  file `"nodeSassConfig": { "binary-path": "" }`.
  * Note: this will supersede default path and
    `SASS_BINARY_PATH` environment variable.
* Allows user to set binary path as parameter to
  invoke any node-sass script with
  `--binary-path` flag.
  * Note: this will supersede default path, path
    as well as the `SASS_BINARY_PATH` environment
    variable.

* This binary path will be used when:
  * Requiring node-sass package.
  * Downloading binary.
  * Uploading binary.

* Wraps all extensions in `process.sass`
  namespace.

Issue URL: #712.
PR URL: #743.
parent 492099e1
#!/usr/bin/env node
var Emitter = require('events').EventEmitter,
Gaze = require('gaze'),
grapher = require('sass-graph'),
......@@ -13,7 +14,7 @@ var Emitter = require('events').EventEmitter,
var cli = meow({
pkg: '../package.json',
version: process.sassInfo,
version: process.sass.versionInfo,
help: [
'Usage',
' node-sass [options] <input.scss> [output.css]',
......
/*!
* node-sass: lib/extensions.js
*/
var eol = require('os').EOL,
flags = require('meow')({ pkg: '../package.json' }).flags,
fs = require('fs'),
package = require('../package.json');
package = require('../package.json'),
path = require('path');
/**
* Get Runtime Info
......@@ -24,26 +30,105 @@ function getRuntimeInfo() {
}
/**
* Get unique name of binary for current platform
* Get binary name.
* If environment variable SASS_BINARY_NAME or
* process aurgument --binary-name is provide,
* return it as is, otherwise make default binary
* name: {platform}-{arch}-{v8 version}.node
*
* @api private
*/
function getBinaryIdentifiableName() {
function getBinaryName() {
var binaryName;
if (flags.binaryName) {
binaryName = flags.binaryName;
} else if (package.nodeSassConfig && package.nodeSassConfig.binaryName) {
binaryName = package.nodeSassConfig.binaryName;
} else if (process.env.SASS_BINARY_NAME) {
binaryName = process.env.SASS_BINARY_NAME;
} else {
var v8SemVersion = process.versions.v8.split('.').slice(0, 3).join('.');
return [process.platform, '-',
binaryName = [process.platform, '-',
process.arch, '-',
v8SemVersion].join('');
}
return [binaryName, 'binding.node'].join('_');
}
/**
* Retrieve the URL to fetch binary.
* If environment variable SASS_BINARY_URL
* is set, return that path. Otherwise make
* path using current release version and
* binary name.
*
* @api private
*/
function getBinaryUrl() {
return flags.binaryUrl ||
package.nodeSassConfig ? package.nodeSassConfig.binaryUrl : null ||
process.env.SASS_BINARY_URL ||
['https://github.com/sass/node-sass/releases/download//v',
package.version, '/', sass.binaryName].join('');
}
function getSassInfo() {
/**
* Get Sass version information
*
* @api private
*/
function getVersionInfo() {
return [
['node-sass', package.version, '(Wrapper)', '[JavaScript]'].join('\t'),
['libsass ', package.libsass, '(Sass Compiler)', '[C/C++]'].join('\t'),
].join(eol);
}
process.runtime = getRuntimeInfo();
process.sassInfo = getSassInfo();
process.sassBinaryName = getBinaryIdentifiableName();
var sass = process.sass = {};
sass.binaryName = getBinaryName();
sass.binaryUrl = getBinaryUrl();
sass.runtime = getRuntimeInfo();
sass.versionInfo = getVersionInfo();
/**
* Get binary path.
* If environment variable SASS_BINARY_PATH or
* process aurgument --binary-path is provide,
* select it by appending binary name, otherwise
* make default binary path using binary name.
* Once the primary selection is made, check if
* callers wants to throw if file not exists before
* returning.
*
* @param {Boolean} throwIfNotExists
* @api private
*/
sass.getBinaryPath = function(throwIfNotExists) {
var binaryPath;
if (flags.binaryPath) {
binaryPath = flags.binaryPath;
} else if (package.nodeSassConfig && package.nodeSassConfig.binaryPath) {
binaryPath = package.nodeSassConfig.binaryPath;
} else if (process.env.SASS_BINARY_PATH) {
binaryPath = process.env.SASS_BINARY_PATH;
} else {
binaryPath = path.join(__dirname, '..', 'vendor', sass.binaryName.replace(/_/, '/'));
}
if (!fs.existsSync(binaryPath) && throwIfNotExists) {
throw new Error('`libsass` bindings not found. Try reinstalling `node-sass`?');
}
return binaryPath;
};
sass.binaryPath = sass.getBinaryPath();
var fs = require('fs'),
path = require('path'),
/*!
* node-sass: lib/index.js
*/
var path = require('path'),
util = require('util');
require('./extensions');
/**
* Get binding
*
* @api private
* Require binding
*/
function getBinding() {
var candidates = [
path.join(__dirname, '..', 'build', 'Debug', 'binding.node'),
path.join(__dirname, '..', 'build', 'Release', 'binding.node'),
path.join(__dirname, '..', 'vendor', process.sassBinaryName, 'binding.node')
];
var candidate = candidates.filter(fs.existsSync).shift();
if (!candidate) {
throw new Error('`libsass` bindings not found. Try reinstalling `node-sass`?');
}
return candidate;
}
var binding = require(process.sass.getBinaryPath(true));
/**
* Get input file
......@@ -150,12 +137,6 @@ function getOptions(options, cb) {
}
/**
* Require binding
*/
var binding = require(getBinding());
/**
* Render
*
* @param {Object} options
......@@ -246,4 +227,4 @@ module.exports.renderSync = function(options) {
* @api public
*/
module.exports.info = process.sassInfo;
module.exports.info = process.sass.versionInfo;
var fs = require('fs'),
chalk = require('chalk'),
sass = require('./'),
/*!
* node-sass: lib/render.js
*/
var chalk = require('chalk'),
fs = require('fs'),
mkdirp = require('mkdirp'),
path = require('path'),
mkdirp = require('mkdirp');
sass = require('./');
/**
* Render
......
/*!
* node-sass: scripts/build.js
*/
var eol = require('os').EOL,
fs = require('fs'),
mkdir = require('mkdirp'),
......@@ -14,11 +18,10 @@ require('../lib/extensions');
*/
function afterBuild(options) {
var folder = options.debug ? 'Debug' : 'Release';
var target = path.join(__dirname, '..', 'build', folder, 'binding.node');
var install = path.join(__dirname, '..', 'vendor', process.sassBinaryName, 'binding.node');
var install = process.sass.binaryPath;
var target = path.join(__dirname, '..', 'build', options.debug ? 'Debug' : 'Release', 'binding.node');
mkdir(path.join(__dirname, '..', 'vendor', process.sassBinaryName), function(err) {
mkdir(path.dirname(install), function(err) {
if (err && err.code !== 'EEXIST') {
console.error(err.message);
return;
......@@ -36,7 +39,7 @@ function afterBuild(options) {
return;
}
console.log('Installed in `' + install + '`');
console.log('Installed in `', install, '`');
});
});
});
......@@ -52,9 +55,9 @@ function afterBuild(options) {
function build(options) {
var arguments = [path.join('node_modules', 'pangyp', 'bin', 'node-gyp'), 'rebuild'].concat(options.args);
console.log(['Building:', process.runtime.execPath].concat(arguments).join(' '));
console.log(['Building:', process.sass.runtime.execPath].concat(arguments).join(' '));
var proc = spawn(process.runtime.execPath, arguments, {
var proc = spawn(process.sass.runtime.execPath, arguments, {
stdio: [0, 1, 2]
});
......@@ -110,12 +113,13 @@ function testBinary(options) {
return build(options);
}
fs.stat(path.join(__dirname, '..', 'vendor', process.sassBinaryName, 'binding.node'), function(err) {
if (err) {
try {
process.sass.getBinaryPath(true);
} catch (e) {
return build(options);
}
console.log('`' + process.sassBinaryName + '` exists; testing.');
console.log('`', process.sass.binaryPath, '` exists.', eol, 'testing binary.');
try {
require('../').renderSync({
......@@ -128,7 +132,6 @@ function testBinary(options) {
return build(options);
}
});
}
/**
......
var path = require('path'),
spawn = require('child_process').spawn,
bin = path.join.bind(null, __dirname, '..', 'node_modules', '.bin');
/*!
* node-sass: scripts/coverage.js
*/
require('../lib/extensions');
var bin = require('path').join.bind(null, __dirname, '..', 'node_modules', '.bin'),
spawn = require('child_process').spawn;
/**
* Run test suite
......@@ -14,7 +19,7 @@ function suite() {
var coveralls = spawn(bin('coveralls'));
var args = [bin('_mocha')].concat(['--reporter', 'mocha-lcov-reporter']);
var mocha = spawn(process.execPath, args, {
var mocha = spawn(process.sass.runtime.execPath, args, {
env: process.env
});
......
/*!
* node-sass: scripts/install.js
*/
var fs = require('fs'),
path = require('path'),
request = require('request'),
mkdirp = require('mkdirp'),
mkdir = require('mkdirp'),
npmconf = require('npmconf'),
packageInfo = require('../package.json');
path = require('path'),
request = require('request');
require('../lib/extensions');
......@@ -24,7 +27,7 @@ function download(url, dest, cb) {
request.get(url, options).on('response', function(response) {
if (response.statusCode < 200 || response.statusCode >= 300) {
returnError('Can not download file from ' + url);
returnError(['Can not download file from:', url].join());
return;
}
......@@ -64,49 +67,31 @@ function applyProxy(options, cb) {
}
/**
* Check if binaries exists
* Check and download binary
*
* @api private
*/
function checkAndFetchBinaries() {
fs.exists(path.join(__dirname, '..', 'vendor', process.sassBinaryName), function (exists) {
if (exists) {
function checkAndDownloadBinary() {
try {
process.sass.getBinaryPath(true);
} catch (e) {
return;
}
fetch();
});
}
/**
* Fetch binaries
*
* @api private
*/
function fetch() {
var url = [
'https://raw.githubusercontent.com/sass/node-sass-binaries/v',
packageInfo.version, '/', process.sassBinaryName,
'/binding.node'
].join('');
var dir = path.join(__dirname, '..', 'vendor', process.sassBinaryName);
var dest = path.join(dir, 'binding.node');
mkdirp(dir, function(err) {
mkdirp(path.dirname(process.sass.binaryPath), function(err) {
if (err) {
console.error(err);
return;
}
download(url, dest, function(err) {
download(process.sass.binaryUrl, process.sass.binaryPath, function(err) {
if (err) {
console.error(err);
return;
}
console.log('Binary downloaded and installed at ' + dest);
console.log('Binary downloaded and installed at', process.sass.binaryPath);
});
});
}
......@@ -121,7 +106,7 @@ if (process.env.SKIP_SASS_BINARY_DOWNLOAD_FOR_CI) {
}
/**
* Run
* If binary does not exsit, download it
*/
checkAndFetchBinaries();
checkAndDownloadBinary();
/*!
* node-sass: scripts/upload.js
*/
require('../lib/extensions');
var flags = require('meow')({ pkg: '../' }).flags;
var fetchReleaseInfoUrl = ['https://api.github.com/repos/sass/node-sass/releases/tags/v',
var eol = require('os').EOL,
fetchReleaseInfoUrl = ['https://api.github.com/repos/sass/node-sass/releases/tags/v',
flags.tag ? flags.tag : require('../package.json').version].join(''),
file = flags.path ?
flags.path :
require('path').resolve(__dirname, '..', 'vendor', process.sassBinaryName, 'binding.node'),
file = flags.path ? flags.path : process.sass.binaryPath,
fs = require('fs'),
os = require('os'),
request = require('request'),
uploadReleaseAssetUrl = ['?name=', process.sassBinaryName, '.node', '&label=', process.sassBinaryName].join('');
uploadReleaseAssetUrl = ['?name=', process.sass.binaryName].join('');
/**
* Upload binary using GitHub API
......@@ -45,11 +43,13 @@ function uploadBinary() {
if (formattedResponse.errors) {
throwFormattedError(formattedResponse.errors);
} else if (res.statusCode > 399) {
throwFormattedError(formattedResponse);
}
console.log(['Binary uploaded successfully.',
'Please test the following link before announcement it:',
formattedResponse.browser_download_url].join(os.EOL));
'Please test the following link before announcing it:',
formattedResponse.browser_download_url].join(eol));
});
};
......@@ -75,7 +75,7 @@ function uploadBinary() {
function throwFormattedError(err) {
throw new Error([
'Error uploading release asset.',
'The server returned:', JSON.stringify(err)].join(os.EOL));
'The server returned:', JSON.stringify(err)].join(eol));
}
/**
......
......@@ -24,7 +24,7 @@ void prepare_import_results(Local<Value> returned_value, sass_context_wrapper* c
ctx_w->imports = sass_make_import_list(array->Length());
for (size_t i = 0; i < array->Length(); ++i) {
Local<Value> value = array->Get(i);
Local<Value> value = array->Get(static_cast<uint32_t>(i));
if (!value->IsObject())
continue;
......@@ -186,12 +186,12 @@ int get_result(sass_context_wrapper* ctx_w, Sass_Context* ctx, bool is_sync = fa
const char* css = sass_context_get_output_string(ctx);
const char* map = sass_context_get_source_map_string(ctx);
NanNew(ctx_w->result)->Set(NanNew("css"), NanNewBufferHandle(css, strlen(css)));
NanNew(ctx_w->result)->Set(NanNew("css"), NanNewBufferHandle(css, static_cast<uint32_t>(strlen(css))));
get_stats(ctx_w, ctx);
if (map) {
NanNew(ctx_w->result)->Set(NanNew("map"), NanNewBufferHandle(map, strlen(map)));
NanNew(ctx_w->result)->Set(NanNew("map"), NanNewBufferHandle(map, static_cast<uint32_t>(strlen(map))));
}
}
else if (is_sync) {
......
......@@ -104,20 +104,16 @@ describe('api', function() {
});
it('should throw error when libsass binary is missing.', function(done) {
var originalBin = path.join('vendor', process.sassBinaryName, 'binding.node'),
var originalBin = process.sass.binaryPath,
renamedBin = [originalBin, '_moved'].join('');
assert.throws(function() {
// un-require node-sass
var resolved = require.resolve('../lib');
delete require.cache[resolved];
fs.renameSync(originalBin, renamedBin);
// try to re-require it
require('../lib');
process.sass.getBinaryPath(true);
}, function(err) {
if ((err instanceof Error) && /`libsass` bindings not found. Try reinstalling `node-sass`?/.test(err)) {
fs.renameSync(renamedBin, originalBin);
if ((err instanceof Error) && /`libsass` bindings not found. Try reinstalling `node-sass`?/.test(err)) {
done();
return true;
}
......
......@@ -201,8 +201,8 @@ describe('cli', function() {
bin.on('close', function() {
assert.equal(read(destCss, 'utf8').trim(), expectedCss);
assert.equal(read(destMap, 'utf8').trim(), expectedMap);
fs.unlinkSync(destMap);
fs.unlinkSync(destCss);
fs.unlinkSync(destMap);
done();
});
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment