diff --git a/lib/command/build.js b/lib/command/build.js index e4ab637d..b7a0e61e 100644 --- a/lib/command/build.js +++ b/lib/command/build.js @@ -562,6 +562,9 @@ build._is_type = function(build_type, type){ build.copy_csses = function (options, callback) { var css = options.pkg.css; var build_type = options.build_type; + var symlink = options.symlink; + var common_root; + if (!css) { return callback(null); } @@ -575,6 +578,12 @@ build.copy_csses = function (options, callback) { if(build_type == 'css'){ css = [node_path.relative(options.cwd, options.file)]; + } else if (symlink && (common_root = self.parse_common_root(css))) { + var linkFrom = node_path.join(options.to, common_root); + var linkTo = node_path.join(options.cwd, common_root); + + self.symlink(linkFrom, linkTo, callback); + return; } async.eachSeries(css, function (path, done) { @@ -625,6 +634,32 @@ build.copy_csses = function (options, callback) { }, callback); }; +// Accept a file list and return their longest common prefix +// NOTICE: +// every file path should be relative to cwd and not beyond cwd +// if no common path except cwd, return undefined +build.parse_common_root = function(files) { + var all_paths = files.filter(function(file) { + return file.indexOf('.' + node_path.sep) == 0; + }); + + if (!all_paths.length) {return;} + + all_paths = all_paths.map(function(file) { + return file.split(node_path.sep); + }); + + var i, len, is_common; + for (i = 0, len = all_paths[0].length; i < len; i++) { + is_common = all_paths.every(function(paths) { + return paths.length > i && paths[i] == all_paths[0][i]; + }); + if (!is_common) break; + } + + return i ? all_paths[0].slice(0, i).join(node_path.sep) : ''; +}; + build.parse_css_images = function(csspath, done){ var self = this; @@ -674,6 +709,7 @@ build.copy_directories = function(options, callback) { var to = options.to; var file = options.file; var build_type = options.build_type; + var symlink = options.symlink; if(!this._is_type(build_type, 'dir')){ return callback(null); @@ -701,6 +737,15 @@ build.copy_directories = function(options, callback) { async.eachSeries(tasks, function (name, done) { var dir = directories[name]; + + if (symlink) { + var linkTo = node_path.join(cwd, dir); + var linkFrom = node_path.join(to, dir); + + self.symlink(linkFrom, linkTo, done); + return; + } + self.copy(cwd, to, dir, function (err) { if (err && err.code === 'SRC_NOT_FOUND') { err = { @@ -718,16 +763,25 @@ build.copy_directories = function(options, callback) { }, callback); }; +// Creates a symlink from `from` to `to`. +build.symlink = function(from, to, callback) { + var self = this; + + fs.lstat(to, function(err, stats) { + if (err) { + return callback(err); + } + + self.logger.info(' {{cyan link}} ' + from + ' -> ' + to); + ln.link(from, to, callback); + }); +} // Copy item from `from` to `to` // @param {String=} item If is undefined, will copy `from` to `to` // @param {Boolean} strict build.copy = function(from, to, item, callback, strict) { var self = this; - if (from === to) { - callback(null); - return; - } if (item) { if (item != item.toLowerCase()) { @@ -739,6 +793,16 @@ build.copy = function(from, to, item, callback, strict) { to = node_path.join(to, item); } + // after fs-extra #198 is solved, can delete this check + try{ + var fromStats = fs.statSync(from); + var toStats = fs.statSync(to); + if (fromStats && toStats && fromStats.ino === toStats.ino) { + callback(null); + return; + } + } catch(e) {} + fs.exists(from, function (exists) { if (!exists) { // if strict and the source is not found, an error will throw. diff --git a/lib/command/watch.js b/lib/command/watch.js index 23e03a24..97b2878c 100644 --- a/lib/command/watch.js +++ b/lib/command/watch.js @@ -225,6 +225,11 @@ watch._rebuild = function(options, cwd, init) { argv.push("--prerelease", prerelease); } + var symlink = options.symlink; + if (symlink) { + argv.push("--symlink", "true"); + } + var commander = self.commander; var parsed = commander.parse(argv, function(err, result, details) { if (err) { diff --git a/lib/option/build.js b/lib/option/build.js index c0969bc9..54e24ffa 100644 --- a/lib/option/build.js +++ b/lib/option/build.js @@ -79,6 +79,13 @@ exports.options = { default: false }, + symlink: { + enumerable: false, + type: Boolean, + info: 'create symbolic links, instead of copying css files and directories', + default: false + }, + prerelease: { enumerable: false, info: 'build as a pre-release package.' diff --git a/lib/option/watch.js b/lib/option/watch.js index c60f9874..75438b4f 100644 --- a/lib/option/watch.js +++ b/lib/option/watch.js @@ -54,6 +54,13 @@ exports.options = { info: 'whether cortex should build the project when begins to watch.', default: true }, + + symlink: { + enumerable: false, + type: Boolean, + info: 'create symbolic links, instead of copying css files and directories', + default: false + }, prerelease: { enumerable: false,