Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

Commit

Permalink
Merge pull request #1103 from caridy/windows
Browse files Browse the repository at this point in the history
closes #264, #460, #1097, #869 and #1063: adding support for windows; dropping support for nodejs 0.6
  • Loading branch information
caridy committed May 17, 2013
2 parents ba2d69a + 4f444ce commit 727475d
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 46 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Expand Up @@ -2,7 +2,6 @@ language: node_js
node_js:
- "0.10"
- "0.8"
- "0.6"
env:
- "testtype=unit"
- "testtype=func"
Expand Down
6 changes: 5 additions & 1 deletion HISTORY.md
Expand Up @@ -14,13 +14,17 @@ change that object, because it might affects other mojits in the same page.

Deprecations, Removals
----------------------
* PR [#1103] Droping support for `nodejs` 0.6.
* `ac.staticAppConfig` was a private api used by mojito to allocate static config for the app,
and this is now removed. If you need access to the config, you can use `mojito-config-addon`
to access `ac.config.getAppConfig()`.

Features
--------

* PR [#1103] Bringing `windows` to the front row by adding *partial* support for mojito on
windows. We plan to consolidate this going forward, but until after [travis-ci.org](http://travis-ci.org/)
supports `windows` [environment](http://about.travis-ci.org/docs/user/ci-environment/) as part of the
build process to do sanity check, we cannot guarantee that everything will work on `windows`.
* `mojito-composite-addon` and `mojito-partial-addon` support `ac.flush` from child mojits.
* Add command "npm test" to run all mojito unit and functional tests with Phantomjs.
Test results can be found under <mojitosrcdir>/artifacts/arrowreport by default.
Expand Down
9 changes: 5 additions & 4 deletions lib/app/addons/rs/url.js
Expand Up @@ -23,6 +23,7 @@ YUI.add('addon-rs-url', function(Y, NAME) {
var libfs = require('fs'),
liburl = require('url'),
libpath = require('path'),
libutil = require('../../../util.js'),
existsSync = libfs.existsSync || libpath.existsSync,
URL_PARTS = ['frameworkName', 'appName', 'prefix'],
// TODO: needs a more future-proof way to do this
Expand Down Expand Up @@ -152,7 +153,7 @@ YUI.add('addon-rs-url', function(Y, NAME) {
var env = evt.args.env,
mojitRes = evt.args.mojitRes,
details = evt.mojitDetails;
details.assetsRoot = mojitRes.url + '/assets';
details.assetsRoot = libutil.webpath(mojitRes.url, 'assets');
},


Expand Down Expand Up @@ -182,7 +183,7 @@ YUI.add('addon-rs-url', function(Y, NAME) {
// in conjuntion with "base", "comboBase" and "root"
// from application.json->yui->config
urlParts.push(res.yui.name + '.js');
res.url = urlParts.join('/');
res.url = libutil.webpath(urlParts);
return;
}

Expand Down Expand Up @@ -212,13 +213,13 @@ YUI.add('addon-rs-url', function(Y, NAME) {

if ('mojit' === res.type) {
if ('shared' !== res.name) {
res.url = urlParts.join('/');
res.url = libutil.webpath(urlParts);
}
return;
}

urlParts.push(relativePath);
res.url = urlParts.join('/');
res.url = libutil.webpath(urlParts);
}


Expand Down
8 changes: 4 additions & 4 deletions lib/app/addons/rs/yui.js
Expand Up @@ -26,6 +26,7 @@ YUI.add('addon-rs-yui', function(Y, NAME) {
libvm = require('vm'),
libmime = require('mime'),
liburl = require('url'),
libutil = require('../../../util.js'),

WARN_SERVER_MODULES = /\b(dom-[\w\-]+|node-[\w\-]+|io-upload-iframe)/ig,
MODULE_SUBDIRS = {
Expand Down Expand Up @@ -130,7 +131,6 @@ YUI.add('addon-rs-yui', function(Y, NAME) {
'},"",{requires:["loader-base"]});'
};


function RSAddonYUI() {
RSAddonYUI.superclass.constructor.apply(this, arguments);
}
Expand Down Expand Up @@ -163,7 +163,7 @@ YUI.add('addon-rs-yui', function(Y, NAME) {

this.staticAppConfig = config.host.getStaticAppConfig() || {};
this.staticHandling = this.staticAppConfig.staticHandling || {};
this.staticPrefix = libpath.join('/', (this.staticHandling.prefix || 'static'), "/");
this.staticPrefix = libutil.webpath('/', (this.staticHandling.prefix || 'static'), "/");
this.yuiConfig = (this.staticAppConfig.yui && this.staticAppConfig.yui.config) || {};
this.langs = {}; // keys are list of languages in the app, values are simply "true"
this.resContents = {}; // res.id: contents
Expand Down Expand Up @@ -253,7 +253,7 @@ YUI.add('addon-rs-yui', function(Y, NAME) {
*/
getYUIConfig: function(ctx) {
var version = Y.version,
yuiPrefix = libpath.join(this.staticPrefix, 'yui/'),
yuiPrefix = libutil.webpath(this.staticPrefix, 'yui/'),
appConfig = this.get('host').getAppConfig(ctx),
yuiConfig;

Expand Down Expand Up @@ -779,7 +779,7 @@ YUI.add('addon-rs-yui', function(Y, NAME) {
modules[name] = store.makeStaticHandlerDetails({
type: 'yui-module',
name: name,
url: libpath.join(this.staticPrefix, 'yui', modules[name].path),
url: libutil.webpath(this.staticPrefix, 'yui', modules[name].path),
path: modules[name].path,
source: {
fs: {
Expand Down
38 changes: 14 additions & 24 deletions lib/app/autoload/store.server.js
Expand Up @@ -102,14 +102,15 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
'model': 'server',
'spec': 'common',
'view': 'common'
};
},
PATH_SEP = require('path').sep;

libs.fs = require('fs');
libs.glob = require('glob');
libs.path = require('path');
libs.semver = require('semver');
libs.walker = require('./package-walker.server');

libs.util = require('../../util.js');

// The Affinity object is to manage the use of the affinity string in
// filenames. Some files have affinities that have multiple parts
Expand Down Expand Up @@ -704,7 +705,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
if (res.type === 'view') {
template = {
'content-path': (env === 'client' ?
this._libs.path.join(this._appConfigStatic.pathToRoot || '', res.url) :
this._libs.util.webpath(this._appConfigStatic.pathToRoot || '', res.url) :
res.source.fs.fullPath),
'content': res.content,
'engine': res.view.engine
Expand Down Expand Up @@ -792,9 +793,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
for (p = 0; p < routesFiles.length; p += 1) {
path = routesFiles[p];
// relative paths are relative to the application
if ('/' !== path.charAt(1)) {
path = this._libs.path.join(this._config.root, path);
}
path = this._libs.path.resolve(this._config.root, path);
routes = this.config.readConfigYCB(path, ctx);
Y.mix(out, routes, true);
}
Expand Down Expand Up @@ -1035,7 +1034,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
rootDir: dir,
rootType: dirType,
subDir: subdir,
subDirArray: subdir.split('/'),
subDirArray: subdir.split(PATH_SEP),
isFile: isFile,
ext: this._libs.path.extname(file)
};
Expand Down Expand Up @@ -1344,7 +1343,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
Y.log('invalid ' + type + ' filename. skipping ' + fs.fullPath, 'warn', NAME);
return;
}
res.name = this._libs.path.join(fs.subDirArray.join('/'), baseParts.join('.'));
res.name = this._libs.util.webpath(fs.subDirArray.join(PATH_SEP), baseParts.join('.'));
res.id = [res.type, res.subtype, res.name].join('-');
// special case
if ('addon' === type && ADDON_SUBTYPES_APPLEVEL[res.subtype]) {
Expand All @@ -1370,7 +1369,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
Y.log('invalid ' + type + ' filename. skipping ' + fs.fullPath, 'warn', NAME);
return;
}
res.name = this._libs.path.join(fs.subDirArray.join('/'), baseParts.join('.'));
res.name = this._libs.util.webpath(fs.subDirArray.join(PATH_SEP), baseParts.join('.'));
res.id = [res.type, res.subtype, res.name].join('-');
return res;
}
Expand All @@ -1388,7 +1387,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
Y.log('invalid spec filename. skipping ' + source.fs.fullPath, 'warn', NAME);
return;
}
res.name = this._libs.path.join(source.fs.subDir, baseParts.join('.'));
res.name = this._libs.util.webpath(source.fs.subDir, baseParts.join('.'));
res.id = [res.type, res.subtype, res.name].join('-');
return res;
}
Expand All @@ -1414,7 +1413,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
Y.log('invalid view filename. skipping ' + fs.fullPath, 'warn', NAME);
return;
}
res.name = this._libs.path.join(fs.subDirArray.join('/'), baseParts.join('.'));
res.name = this._libs.util.webpath(fs.subDirArray.join(PATH_SEP), baseParts.join('.'));
res.id = [res.type, res.subtype, res.name].join('-');
// for performance reasons, we might want to preload all
// views in memory.
Expand Down Expand Up @@ -1781,11 +1780,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
children,
childName,
childPath;

if ('/' !== dir.charAt(0)) {
dir = this._libs.path.join(this._config.root, dir);
}

dir = this._libs.path.resolve(this._config.root, dir);
if (!(this._libs.fs.existsSync || this._libs.path.existsSync)(dir)) {
return;
}
Expand Down Expand Up @@ -1819,10 +1814,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
ress,
r,
res;

if ('/' !== dir.charAt(0)) {
dir = this._libs.path.join(this._config.root, dir);
}
dir = this._libs.path.resolve(this._config.root, dir);

if (!(this._libs.fs.existsSync || this._libs.path.existsSync)(dir)) {
return;
Expand Down Expand Up @@ -1990,7 +1982,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
if ('object' === typeof ret) {
if (ret.skipSubdirParts) {
source.fs.subDirArray = source.fs.subDirArray.slice(ret.skipSubdirParts);
source.fs.subDir = source.fs.subDirArray.join('/') || '.';
source.fs.subDir = source.fs.subDirArray.join(PATH_SEP) || '.';
}
res = me.parseResourceVersion(source, ret.type, ret.subtype, mojitType);
if ('object' === typeof res) {
Expand Down Expand Up @@ -2104,9 +2096,7 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
glob;
for (i = 0; i < list.length; i += 1) {
glob = list[i];
if ('/' !== glob.charAt(0)) {
glob = this._libs.path.join(prefix, glob);
}
glob = this._libs.path.resolve(prefix, glob);
found = found.concat(this._libs.glob.sync(glob, {}));
}
return found;
Expand Down
3 changes: 2 additions & 1 deletion lib/app/middleware/mojito-handler-static.js
Expand Up @@ -28,6 +28,7 @@
*/
var liburl = require('url'),
libpath = require('path'),
libutil = require('../../util.js'),

NAME = 'StaticHandler';

Expand Down Expand Up @@ -177,7 +178,7 @@ function staticProvider(store, logger, Y) {
options = appConfig.staticHandling || {},
cache = options.cache,
maxAge = options.maxAge,
staticPath = liburl.resolve('/', (options.prefix || 'static') + '/'),
staticPath = libutil.webpath(liburl.resolve('/', (options.prefix || 'static') + '/')),
comboPath = '/combo~';

if (cache && !maxAge) {
Expand Down
6 changes: 4 additions & 2 deletions lib/app/middleware/mojito-handler-tunnel-parser.js
Expand Up @@ -17,6 +17,7 @@ var RE_TRAILING_SLASHES = /\/+$/;
module.exports = function (config) {
var liburl = require('url'),
libpath = require('path'),
libutil = require('../../util.js'),
appConfig = config.store.getAppConfig({}) || {},
staticPrefix,
tunnelPrefix;
Expand All @@ -34,8 +35,9 @@ module.exports = function (config) {
tunnelPrefix = libpath.normalize('/' + tunnelPrefix);
}

staticPrefix = staticPrefix || '/static';
tunnelPrefix = tunnelPrefix || '/tunnel';
// normalizing the prefixes (this helps with windows runtime)
staticPrefix = libutil.webpath(staticPrefix || '/static');
tunnelPrefix = libutil.webpath(tunnelPrefix || '/tunnel');

return function (req, res, next) {
var hasTunnelPrefix = req.url.indexOf(tunnelPrefix) === 0,
Expand Down
38 changes: 38 additions & 0 deletions lib/util.js
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2013, Yahoo! Inc. All rights reserved.
* Copyrights licensed under the New BSD License.
* See the accompanying LICENSE file for terms.
*/

/*jslint node:true, nomen: true */

'use strict';

var libpath = require('path');

/**
Produces a normalized web path by joining all the parts and normalizing the
filesystem-like path into web compatible url. This is useful when you have to
generate urls based on filesystem path where unix uses `/` and windows uses `\\`.
Node is pretty smart and it will do the heavy lifting, we just need to adjust
the separtor so it uses the `/`. This method also support relative and absolute
paths.
util.webpath('foo/bar' ,'baz');
// => foo/bar/baz
util.webpath('foo\\bar', 'baz/');
// => foo/bar/baz/
util.webpath('./foo/bar', './baz');
// => foo/bar/baz
util.webpath(['foo', 'bar', 'baz']);
// => foo/bar/baz
@method webpath
@param {Array|String*} url the list of parts to be joined and normalized
@return {String} The joined and normalized url
**/
exports.webpath = function (url) {
var args = [].concat.apply([], arguments),
parts = libpath.join.apply(libpath, args).split(libpath.sep);
return parts.join('/');
};
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -45,7 +45,7 @@
"mojito": "bin/mojito"
},
"engines": {
"node": ">0.4",
"node": ">0.6",
"npm": ">1.0"
},
"devDependencies": {
Expand All @@ -59,7 +59,7 @@
"phantomjs": ">=1.8.0"
},
"scripts": {
"test": "cd tests && ./run.js test --browser phantomjs"
"test": "cd tests && node run.js test --browser phantomjs"
},
"homepage": "http://developer.yahoo.com/cocktails/mojito/",
"repository": {
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/lib/app/autoload/test-store.server.js
Expand Up @@ -216,14 +216,14 @@ YUI().use(
'server mojit view index.hb.html is loaded correctly': function() {
var instance = {type:'TestMojit3'};
store.expandInstance(instance, {}, function(err, instance){
A.areSame('index.hb.html', instance.views.index['content-path'].split('/').pop());
A.areSame('index.hb.html', instance.views.index['content-path'].split(libpath.sep).pop());
});
},

'server mojit view index.iphone.hb.html is loaded correctly': function(){
var instance = {type:'TestMojit3'};
store.expandInstance(instance, {device:'iphone'}, function(err, instance){
A.areSame('index.iphone.hb.html', instance.views.index['content-path'].split('/').pop());
A.areSame('index.iphone.hb.html', instance.views.index['content-path'].split(libpath.sep).pop());
});
},

Expand Down
9 changes: 5 additions & 4 deletions tests/unit/lib/app/commands/test-gv.js
Expand Up @@ -113,15 +113,16 @@ YUI().use('mojito-test-extra', 'test', 'json-parse', 'json-stringify', function(
callbackCalled = true;
});
A.areSame(3, mockFs._log.length);
Y.TEST_CMP(['mkdirSync', fixtures + '/artifacts', 511], mockFs._log[0]);
Y.TEST_CMP(['mkdirSync', fixtures + '/artifacts/gv', 511], mockFs._log[1]);
Y.TEST_CMP(['mkdirSync', libpath.join(fixtures, '/artifacts'), 511], mockFs._log[0]);
Y.TEST_CMP(['mkdirSync', libpath.join(fixtures + '/artifacts/gv'), 511], mockFs._log[1]);
Y.TEST_CMP('writeFileSync', mockFs._log[2][0]);
Y.TEST_CMP(fixtures + '/artifacts/gv/yui.server.dot', mockFs._log[2][1]);
Y.TEST_CMP(libpath.join(fixtures + '/artifacts/gv/yui.server.dot'), mockFs._log[2][1]);

A.isTrue(callbackCalled, 'callback called');
A.areSame(2, mockConsole._log.length, 'right number of log messages');
A.areSame('Dotfile generated. To turn it into a graph, run the following:', mockConsole._log[0]);
A.areSame('$ dot -Tgif artifacts/gv/yui.server.dot > artifacts/gv/yui.server.gif', mockConsole._log[1]);
A.areSame('$ dot -Tgif ' + libpath.join('artifacts/gv/yui.server.dot') + ' > ' +
libpath.join('artifacts/gv/yui.server.gif'), mockConsole._log[1]);

var graph = gvcmd.test.graph;
var want = [
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/lib/app/commands/test-version.js
Expand Up @@ -57,7 +57,8 @@ YUI().use('test', function(Y) {
args: [Y.Mock.Value.Any],
run: function (err) {
A.isTrue(/no such file or directory/.test(err));
A.isTrue(/mojits\/package.json/.test(err));
A.isTrue(/mojits/.test(err));
A.isTrue(/package.json/.test(err));
}
});
libutils.test.setConsole(mockConsole);
Expand Down

0 comments on commit 727475d

Please sign in to comment.