From bd7c0199e7c674f72c35c8e2a67bc3cd05c8546b Mon Sep 17 00:00:00 2001 From: seanmwalker Date: Mon, 20 Jan 2014 01:47:14 -0600 Subject: [PATCH 01/34] Updated paths, added meteorite alias, addressed the HOME env with HOMEPATH, and added in the wich package for fining git, curl and meteor. This seems to work reasonably well in cmd.exe and in cygwin. Still working on test issues though. --- lib/atmosphere.js | 4 ++-- lib/meteor.js | 21 +++++++++++++++++++-- lib/meteorite.js | 7 ++++--- package.json | 5 +++-- spec/acceptance/test_spec.js | 10 +++++++--- spec/support/bin/curl | 5 +++-- spec/support/bin/git | 10 ++++++++-- 7 files changed, 46 insertions(+), 16 deletions(-) diff --git a/lib/atmosphere.js b/lib/atmosphere.js index 89350e4..6d31cd2 100644 --- a/lib/atmosphere.js +++ b/lib/atmosphere.js @@ -15,14 +15,14 @@ var writeUserTokenFile = function(user) { var cfg = { user: user }; - var filePath = path.join(process.env.HOME, '.mrt.cfg'); + var filePath = path.join(process.env.HOME || process.env.HOMEPATH, '.mrt.cfg'); fs.writeFileSync(filePath, JSON.stringify(cfg)); fs.chmodSync(filePath, '0600'); }; var readUserTokenFile = function() { - var filePath = path.join(process.env.HOME, '.mrt.cfg'); + var filePath = path.join(process.env.HOME || process.env.HOMEPATH, '.mrt.cfg'); var fileContents = fs.readFileSync(filePath); return JSON.parse(fileContents); diff --git a/lib/meteor.js b/lib/meteor.js index 14cd228..20d78c4 100644 --- a/lib/meteor.js +++ b/lib/meteor.js @@ -7,6 +7,7 @@ var fstream = require('fstream'); var wrench = require('wrench'); var spawn = require('child_process').spawn; var exec = require('child_process').exec; +var which = require('which'); // A 'Meteor' refers to a single commit (branch, tag) of a version of the core meteor @@ -75,7 +76,8 @@ Meteor.prototype.install = function(buildDevBundle, fn) { } else { // meteor --help installs the dev bundle before doing anything else console.log('Downloading Meteor development bundle'); - var meteor = spawn('./meteor', ['--help'], {cwd: self.source.path}); + //var meteor = spawn('./meteor', ['--help'], {cwd: self.source.path}); + var meteor = spawn(self._executable(), ['--help'], {cwd: self.source.path}); // just output the status bar meteor.stderr.pipe(process.stderr); @@ -95,6 +97,8 @@ Meteor.prototype.ensurePrepared = function(fn) { } }; +/* +// Saving the original function so we can revert quickly once spawn-cmd is in place. Meteor.prototype._executable = function() { var self = this; @@ -104,6 +108,19 @@ Meteor.prototype._executable = function() { return path.join(self.source.packagePath(), 'meteor'); } } +*/ + +// Temporary code to be ripped out once spawn-cmd is in place. +Meteor.prototype._executable = function() { + var self = this; + var executableName = path.basename(which.sync('meteor')); + + if (self.defaultMeteor) { + return executableName; + } else { + return path.join(self.source.packagePath(), executableName); + } +} // run a command using just this checked-out version of meteor Meteor.prototype.execute = function(args, package_dir, fn) { @@ -140,7 +157,7 @@ Meteor.prototype.hasPackage = function(pkgName, fn) { if (!self.packageNames) { // we have to call meteor list because there's no obvious place to look - exec('meteor list', function(error, list) { + exec(self._executable() + ' list', function(error, list) { var lines = list.split('\n'); self.packageNames = _.map(lines, function(l) { diff --git a/lib/meteorite.js b/lib/meteorite.js index a876bcc..006c4e6 100644 --- a/lib/meteorite.js +++ b/lib/meteorite.js @@ -107,9 +107,10 @@ Meteorite.prototype['link-package'] = function(fn) { // pointing to the wrong spot if (old) - fs.unlinkSync(packagePath); + fs.unlinkSync(path.resolve(packagePath)); - fs.symlinkSync(packageDir, packagePath); + // Windows uses junctions to solve for symlinks. They need to be full paths too. + fs.symlinkSync(path.resolve(packageDir), path.resolve(packagePath), 'junction'); } /////// Package level meteorite commands @@ -229,7 +230,7 @@ _.each([ // Class methods Meteorite.root = function() { - var homeDir = process.env.HOME; + var homeDir = process.env.HOME || process.env.HOMEPATH; return path.join(homeDir, '.meteorite'); }; diff --git a/package.json b/package.json index 73218d9..89d6270 100644 --- a/package.json +++ b/package.json @@ -7,13 +7,14 @@ , "dependencies": { "ddp": ">=0.3.1" , "underscore": "1.3.3" - , "wrench": "1.3.9" + , "wrench": ">=1.5.5" , "fstream": ">=0.1.18" , "optimist": ">=0.3.4" , "prompt": "0.2.11" , "colors": "0.6.0-1" , "async": "0.2.9" , "rolling_timeout_exec": ">=0.0.1" + , "which": ">=1.0.5" } , "devDependencies": { "mocha": ">=1.2.2" @@ -28,5 +29,5 @@ { "type" : "git" , "url" : "https://github.com/oortcloud/meteorite.git" } -, "bin" : { "mrt" : "./bin/mrt.js" } +, "bin" : { "mrt" : "./bin/mrt.js", "meteorite" : "./bin/mrt.js" } } diff --git a/spec/acceptance/test_spec.js b/spec/acceptance/test_spec.js index e09494f..96ca734 100644 --- a/spec/acceptance/test_spec.js +++ b/spec/acceptance/test_spec.js @@ -3,6 +3,7 @@ var fs = require('fs'); var wrench = require('wrench'); var _ = require('underscore'); var ddp = require('ddp'); +var which = require('which'); var utils = require('../lib/utils.js'); var atmosphere = require('../lib/atmosphere.js'); @@ -15,8 +16,11 @@ var appDir = path.join(appHome, 'app'); before(function(done){ // ensure our "cached" CURL is in the path + process.env._METEORITE_REAL_GIT = which.sync('git'); process.env.PATH = [path.resolve(path.join('spec', 'support', 'bin')), process.env.PATH].join(':'); - + process.env._METEORITE_REAL_CURL = which.sync('curl'); + process.env._METEORITE_REAL_METEOR = path.basename(which.sync('meteor')); + // make sure Meteor doesn't try to install into our soon to be clean home dir process.env.METEOR_WAREHOUSE_DIR = path.join(process.env.HOME, '.meteor'); @@ -27,7 +31,7 @@ before(function(done){ console.log("Preparing..") // ensure we have the latest dev bundle cached console.log(" Ensuring we have the dev bundle for system meteor"); - utils.downloadDevBundle('meteor', function() { + utils.downloadDevBundle(process.env._METEORITE_REAL_METEOR, function() { // ensure we have dev bundles for all our meteor forks // XXX: // for meteor in meteors/ @@ -62,4 +66,4 @@ beforeEach(function() { } } fs.mkdirSync(appHome); -}); +}); \ No newline at end of file diff --git a/spec/support/bin/curl b/spec/support/bin/curl index ec0d4f3..0a4df89 100755 --- a/spec/support/bin/curl +++ b/spec/support/bin/curl @@ -8,6 +8,7 @@ var wrench = require('wrench'); var args = process.argv; var fileNameParts = args[args.length - 1].split('/'); var fileName = fileNameParts[fileNameParts.length - 1]; +var REAL_CURL = process.env._METEORITE_REAL_CURL; console.error('CURL called for ', fileName); @@ -15,7 +16,7 @@ if (! fileName.match(/^dev_bundle_/)) { // if it's not the dev bundle we are looking for, bail out to standard curl console.error('skipping...') - spawn('/usr/bin/curl', process.argv.slice(2)); + spawn(REAL_CURL, process.argv.slice(2)); } else { // it's a dev bundle, so cache it @@ -35,7 +36,7 @@ if (! fileName.match(/^dev_bundle_/)) { var url = process.argv[process.argv.length - 1]; - var curlCache = spawn('/usr/bin/curl', ['-O', url], { cwd: cachePath }, function() {}); + var curlCache = spawn(REAL_CURL, ['-O', url], { cwd: cachePath }, function() {}); curlCache.on('exit', outputFile); diff --git a/spec/support/bin/git b/spec/support/bin/git index 94f224f..3ec6a3c 100755 --- a/spec/support/bin/git +++ b/spec/support/bin/git @@ -15,6 +15,12 @@ var copyRepo = function(from, to) { spawn('cp', ['-r', from, to]); }; +var REAL_GIT = process.env._METEORITE_REAL_GIT; +if (!REAL_GIT) { + console.error('No _METEORITE_REAL_GIT specified'); + process.exit(1); +} + if (command === 'clone') { var cachePath = path.join(__dirname, '..', 'cache'); @@ -31,7 +37,7 @@ if (command === 'clone') { if (!fs.existsSync(repoCachePath)) { args.push(repoUrl); args.push(repoCachePath); - var git = spawn('/usr/local/bin/git', args); + var git = spawn(REAL_GIT, args); git.on('exit', function() { copyRepo(repoCachePath, destPath); @@ -44,7 +50,7 @@ if (command === 'clone') { } else if (command !== 'pull') { // we will skip pulls, expensive and redudant. - var git = spawn('/usr/local/bin/git', args); + var git = spawn(REAL_GIT, args); git.stderr.pipe(process.stderr); git.stdout.pipe(process.stdout); From 5c7e5b54cefc3e0a2768e894d1c0364297502707 Mon Sep 17 00:00:00 2001 From: yeputons Date: Mon, 20 Jan 2014 15:52:18 +0400 Subject: [PATCH 02/34] #224: spec/acceptance/test_spec.js: ':' --> path.delimiter --- spec/acceptance/test_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/acceptance/test_spec.js b/spec/acceptance/test_spec.js index 96ca734..907ce53 100644 --- a/spec/acceptance/test_spec.js +++ b/spec/acceptance/test_spec.js @@ -17,7 +17,7 @@ var appDir = path.join(appHome, 'app'); before(function(done){ // ensure our "cached" CURL is in the path process.env._METEORITE_REAL_GIT = which.sync('git'); - process.env.PATH = [path.resolve(path.join('spec', 'support', 'bin')), process.env.PATH].join(':'); + process.env.PATH = [path.resolve(path.join('spec', 'support', 'bin')), process.env.PATH].join(path.delimiter); process.env._METEORITE_REAL_CURL = which.sync('curl'); process.env._METEORITE_REAL_METEOR = path.basename(which.sync('meteor')); From 8fde22dbf2321e54099897f8a22352c6ce752ce1 Mon Sep 17 00:00:00 2001 From: yeputons Date: Mon, 20 Jan 2014 16:32:04 +0400 Subject: [PATCH 03/34] #224: test_spec.js: METEOR_WAREHOUSE_DIR issue on win32 was fixed plus now it's changed iff there was no such env variable before --- spec/acceptance/test_spec.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/spec/acceptance/test_spec.js b/spec/acceptance/test_spec.js index 907ce53..0278d07 100644 --- a/spec/acceptance/test_spec.js +++ b/spec/acceptance/test_spec.js @@ -21,8 +21,13 @@ before(function(done){ process.env._METEORITE_REAL_CURL = which.sync('curl'); process.env._METEORITE_REAL_METEOR = path.basename(which.sync('meteor')); - // make sure Meteor doesn't try to install into our soon to be clean home dir - process.env.METEOR_WAREHOUSE_DIR = path.join(process.env.HOME, '.meteor'); + if (!process.env.METEOR_WAREHOUSE_DIR) { + // make sure Meteor doesn't try to install into our soon to be clean home dir + process.env.METEOR_WAREHOUSE_DIR = path.join(process.env.HOME, '.meteor'); + if (process.platform == 'win32') { + process.env.METEOR_WAREHOUSE_DIR = path.join(process.env.LOCALAPPDATA || process.env.APPDATA, '.meteor'); + } + } // set our home dir so we can easily blow away meteorite installs wrench.mkdirSyncRecursive(appHome); From 5f3ce28fc5819987419b9b2f9addef8fbcd822e1 Mon Sep 17 00:00:00 2001 From: yeputons Date: Mon, 20 Jan 2014 16:38:23 +0400 Subject: [PATCH 04/34] #224: `mrt install` was fixed: symlinkSync('junction') is used --- lib/dependencies/package.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/dependencies/package.js b/lib/dependencies/package.js index f624785..3fa1689 100755 --- a/lib/dependencies/package.js +++ b/lib/dependencies/package.js @@ -126,7 +126,8 @@ Package.prototype.installInto = function(project, fn) { // Make link if it doesn't exist, inform caller if (! linkedTo) { - fs.symlinkSync(libPath, packagePath); + // Windows uses junctions to solve for symlinks. They need to be full paths too. + fs.symlinkSync(path.resolve(libPath), path.resolve(packagePath), 'junction'); self.addToGitIgnore(project); if (self._fromAtmosphere) { From 2463d5fdc8831d143a0ecf49290d5d038034bc89 Mon Sep 17 00:00:00 2001 From: yeputons Date: Mon, 20 Jan 2014 17:34:55 +0400 Subject: [PATCH 05/34] #224: spec/lib/runner.js: killProcessFamily() now works on Windows (using taskkill.exe) --- spec/lib/runner.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spec/lib/runner.js b/spec/lib/runner.js index a59afee..986161d 100644 --- a/spec/lib/runner.js +++ b/spec/lib/runner.js @@ -18,6 +18,13 @@ var matchesSpecs = function(output, specs) { // kill the process family described by process, then send done the error var killProcessFamily = function(child, error, done) { + if (process.platform === 'win32') { + // We do not use /PID , because it will fail if process was already terminated + exec('taskkill /F /T /FI "PID eq ' + child.pid + '"', function(killErr) { + done(error || killErr); + }); + return; + } // we need to grab a table of process ids and parent ids to form a tree out of exec('ps -opid -oppid', function(err, rawData) { // parse the list of process ids and parent ids From b7367f26defb4f66719029835f71e7af8e1e0954 Mon Sep 17 00:00:00 2001 From: yeputons Date: Mon, 20 Jan 2014 17:40:43 +0400 Subject: [PATCH 06/34] #224: now folders are pre-created before 'git clone', git on Windows doesn't do that itself --- lib/sources/git.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/sources/git.js b/lib/sources/git.js index cd5fb32..4853a0f 100644 --- a/lib/sources/git.js +++ b/lib/sources/git.js @@ -118,6 +118,7 @@ GitSource.prototype._clone = function(fn) { options = { rollingTimeout: ROLLING_TIMEOUT }; if (!fs.existsSync(this.sourcePath)) { + wrench.mkdirSyncRecursive(this.sourcePath); child = exec(command, options, function(err, stdout, stderr) { if (err) { reportErrors(err, stdout, stderr, timedOut); From 2145236c0ee0fdee816347f9c762f1832fabbc05 Mon Sep 17 00:00:00 2001 From: seanmwalker Date: Mon, 20 Jan 2014 23:21:21 -0600 Subject: [PATCH 07/34] Updating the home env building to support a few alternative situations via a shared function for building the full path based on the subdirectory path provided. Updated the tests to call meteorite instead of mrt, so that windows will be able to execute them as well. There are a lot of tests to address to get the windows execution working at 100%. --- lib/atmosphere.js | 6 ++++-- lib/meteorite.js | 4 ++-- lib/utils/env.js | 15 +++++++++++++++ spec/lib/atmosphere.js | 2 +- 4 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 lib/utils/env.js diff --git a/lib/atmosphere.js b/lib/atmosphere.js index 6d31cd2..f36d1e9 100644 --- a/lib/atmosphere.js +++ b/lib/atmosphere.js @@ -10,19 +10,21 @@ var _ = require('underscore'); var prompt = require('prompt'); var meteoriteArgs = require('optimist').argv; var version = require('../package').version; +var env = require('../lib/utils/env'); var writeUserTokenFile = function(user) { var cfg = { user: user }; - var filePath = path.join(process.env.HOME || process.env.HOMEPATH, '.mrt.cfg'); + + var filePath = env.buildFromHomePath('.mrt.cfg'); fs.writeFileSync(filePath, JSON.stringify(cfg)); fs.chmodSync(filePath, '0600'); }; var readUserTokenFile = function() { - var filePath = path.join(process.env.HOME || process.env.HOMEPATH, '.mrt.cfg'); + var filePath = env.buildFromHomePath('.mrt.cfg'); var fileContents = fs.readFileSync(filePath); return JSON.parse(fileContents); diff --git a/lib/meteorite.js b/lib/meteorite.js index 006c4e6..6fd7875 100644 --- a/lib/meteorite.js +++ b/lib/meteorite.js @@ -4,6 +4,7 @@ var Atmosphere = require('../lib/atmosphere'); var fs = require('fs'); var _ = require('underscore'); var wrench = require('wrench'); +var env = require('../lib/utils/env'); Meteorite = function(args, meteorArgs) { this.args = args; @@ -230,8 +231,7 @@ _.each([ // Class methods Meteorite.root = function() { - var homeDir = process.env.HOME || process.env.HOMEPATH; - return path.join(homeDir, '.meteorite'); + return env.buildFromHomePath('.meteorite'); }; // Creates the path to ~/.meteorite diff --git a/lib/utils/env.js b/lib/utils/env.js new file mode 100644 index 0000000..7c79d33 --- /dev/null +++ b/lib/utils/env.js @@ -0,0 +1,15 @@ +var path = require('path'); + +Env = { + buildFromHomePath: function(subPath) { +/* console.log('process.env.HOME: ' + process.env.HOME); + console.log('process.env.HOMEDRIVE: ' + process.env.HOMEDRIVE); + console.log('process.env.HOMESHARE: ' + process.env.HOMESHARE); + console.log('process.env.HOMEPATH: ' + process.env.HOMEPATH);*/ + + var homeDir = process.env.HOME || (process.env.HOMEDRIVE || process.env.HOMESHARE) + process.env.HOMEPATH; + return path.join(homeDir, subPath); + } +}; + +module.exports = Env; \ No newline at end of file diff --git a/spec/lib/atmosphere.js b/spec/lib/atmosphere.js index 4e45fe2..7a88cff 100644 --- a/spec/lib/atmosphere.js +++ b/spec/lib/atmosphere.js @@ -6,7 +6,7 @@ var async = require('async'); var assert = require('assert'); -var baseCommand = 'mrt --repoHost localhost --repoPort 3333 --repoUsername test --repoPassword testtest' +var baseCommand = 'meteorite --repoHost localhost --repoPort 3333 --repoUsername test --repoPassword testtest' var packagesNeeded = { 'mrt-test-pkg1': ['0.1.0', '0.2.0'], From 127805a861e3977be4d2ae3b4878a3de9a75a268 Mon Sep 17 00:00:00 2001 From: seanmwalker Date: Mon, 20 Jan 2014 23:25:48 -0600 Subject: [PATCH 08/34] Moved the seting of path to the bottom. --- spec/acceptance/test_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/acceptance/test_spec.js b/spec/acceptance/test_spec.js index 0278d07..6dab25a 100644 --- a/spec/acceptance/test_spec.js +++ b/spec/acceptance/test_spec.js @@ -17,9 +17,9 @@ var appDir = path.join(appHome, 'app'); before(function(done){ // ensure our "cached" CURL is in the path process.env._METEORITE_REAL_GIT = which.sync('git'); - process.env.PATH = [path.resolve(path.join('spec', 'support', 'bin')), process.env.PATH].join(path.delimiter); process.env._METEORITE_REAL_CURL = which.sync('curl'); process.env._METEORITE_REAL_METEOR = path.basename(which.sync('meteor')); + process.env.PATH = [path.resolve(path.join('spec', 'support', 'bin')), process.env.PATH].join(path.delimiter); if (!process.env.METEOR_WAREHOUSE_DIR) { // make sure Meteor doesn't try to install into our soon to be clean home dir From 91a2dd74d94dbbb3a6c35cec67a3636a59cb02a7 Mon Sep 17 00:00:00 2001 From: yeputons Date: Wed, 22 Jan 2014 00:15:56 +0400 Subject: [PATCH 09/34] #224: smart_lock_spec.js test were fixed (forward/back slashes mess) --- spec/unit/smart_lock_spec.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/spec/unit/smart_lock_spec.js b/spec/unit/smart_lock_spec.js index 34cb6f1..3679ca7 100644 --- a/spec/unit/smart_lock_spec.js +++ b/spec/unit/smart_lock_spec.js @@ -2,6 +2,7 @@ var _ = require('underscore'); var assert = require('assert'); var Meteorite = require('../../lib/meteorite'); var Dependencies = require('../../lib/dependencies/dependencies'); +var path = require('path'); require('../lib/mocks/package_mock'); require('../lib/mocks/project_mock'); @@ -126,17 +127,17 @@ describe('Writing smart.lock', function() { expected = { packages: { "mrt-test-pkg2": { - "path": "../../mrt-test-pkg2" + "path": path.normalize("../../mrt-test-pkg2") }, "mrt-test-pkg1": { // pkg2 has a link to ../mrt-test-pkg1, so when it resolves, it // should be two levels up - "path": "../../mrt-test-pkg1" + "path": path.normalize("../../mrt-test-pkg1") } }, basePackages: { "mrt-test-pkg2": { - "path": "../../mrt-test-pkg2" + "path": path.normalize("../../mrt-test-pkg2") } } }; From a48f00485e92928ab42daa904adbd3cb8a36647d Mon Sep 17 00:00:00 2001 From: yeputons Date: Wed, 22 Jan 2014 00:46:30 +0400 Subject: [PATCH 10/34] #224: resolver_spec.js: absolute paths were passes through path.resolve() to be consistent with what package.js do on Windows (driver letter issue) --- spec/unit/resolver_spec.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/spec/unit/resolver_spec.js b/spec/unit/resolver_spec.js index a86924a..d70d4c3 100644 --- a/spec/unit/resolver_spec.js +++ b/spec/unit/resolver_spec.js @@ -2,6 +2,7 @@ var _ = require('underscore'); var assert = require('assert'); var Meteorite = require('../../lib/meteorite'); var Dependencies = require('../../lib/dependencies/dependencies'); +var path = require('path'); require('../lib/mocks/package_mock'); require('../lib/mocks/atmosphere_mock'); @@ -33,41 +34,41 @@ var testConflict = function(pkgDefns, fn) { describe('The Resolver', function() { describe('with two local dependencies', function() { - testConflict({A: {path: '/A'}, B: {path: '/B'}}, + testConflict({A: {path: path.resolve('/A')}, B: {path: path.resolve('/B')}}, function(dependencies, done) { - assert.equal(dependencies.packages['C'].source.path, '/C.path.A'); + assert.equal(dependencies.packages['C'].source.path, path.resolve('/C.path.A')); done(); }); }); describe('with a local dependency vs a git one', function() { - testConflict({A: {path: '/A'}, B: {git: 'B'}}, + testConflict({A: {path: path.resolve('/A')}, B: {git: 'B'}}, function(dependencies, done) { - assert.equal(dependencies.packages['C'].source.path, '/C.path.A'); + assert.equal(dependencies.packages['C'].source.path, path.resolve('/C.path.A')); done(); }); }); describe('with a git dependency vs a local one', function() { - testConflict({A: {git: 'A'}, B: {path: '/B'}}, + testConflict({A: {git: 'A'}, B: {path: path.resolve('/B')}}, function(dependencies, done) { - assert.equal(dependencies.packages['C'].source.path, '/C.path.B'); + assert.equal(dependencies.packages['C'].source.path, path.resolve('/C.path.B')); done(); }); }); describe('with a local dependency vs an atmos one', function() { - testConflict({A: {path: '/A'}, B: {}}, + testConflict({A: {path: path.resolve('/A')}, B: {}}, function(dependencies, done) { - assert.equal(dependencies.packages['C'].source.path, '/C.path.A'); + assert.equal(dependencies.packages['C'].source.path, path.resolve('/C.path.A')); done(); }); }); describe('with a atmos dependency vs a local one', function() { - testConflict({A: {}, B: {path: '/B'}}, + testConflict({A: {}, B: {path: path.resolve('/B')}}, function(dependencies, done) { - assert.equal(dependencies.packages['C'].source.path, '/C.path.B'); + assert.equal(dependencies.packages['C'].source.path, path.resolve('/C.path.B')); done(); }); }); From 4e06c99f4c3f278e11181af7ceb653793e988e1e Mon Sep 17 00:00:00 2001 From: seanmwalker Date: Tue, 21 Jan 2014 22:53:29 -0600 Subject: [PATCH 11/34] Refactored how we get the windows vs linux paths, this approach makes windows consistent in both cygwin and cmd. Changed the mrt.js call to use the meteorite.cmd file created by 'npm install'. This fixed 38 tests for me. - TODO: Refactor how we get the paths for tests, fix the 3 remaining tests and clean up a few odds and ends. --- lib/utils/env.js | 10 ++++------ spec/acceptance/test_spec.js | 6 ++---- spec/lib/runner.js | 4 +++- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/utils/env.js b/lib/utils/env.js index 7c79d33..9d27519 100644 --- a/lib/utils/env.js +++ b/lib/utils/env.js @@ -2,12 +2,10 @@ var path = require('path'); Env = { buildFromHomePath: function(subPath) { -/* console.log('process.env.HOME: ' + process.env.HOME); - console.log('process.env.HOMEDRIVE: ' + process.env.HOMEDRIVE); - console.log('process.env.HOMESHARE: ' + process.env.HOMESHARE); - console.log('process.env.HOMEPATH: ' + process.env.HOMEPATH);*/ - - var homeDir = process.env.HOME || (process.env.HOMEDRIVE || process.env.HOMESHARE) + process.env.HOMEPATH; + var homeDir = process.env.HOME + if (process.platform == 'win32') { + var homeDir = process.env.LOCALAPPDATA || process.env.APPDATA; + } return path.join(homeDir, subPath); } }; diff --git a/spec/acceptance/test_spec.js b/spec/acceptance/test_spec.js index 6dab25a..e6b303c 100644 --- a/spec/acceptance/test_spec.js +++ b/spec/acceptance/test_spec.js @@ -6,6 +6,7 @@ var ddp = require('ddp'); var which = require('which'); var utils = require('../lib/utils.js'); +var env = require('../../lib/utils/env.js'); var atmosphere = require('../lib/atmosphere.js'); // this is our home dir for running mrt against @@ -23,10 +24,7 @@ before(function(done){ if (!process.env.METEOR_WAREHOUSE_DIR) { // make sure Meteor doesn't try to install into our soon to be clean home dir - process.env.METEOR_WAREHOUSE_DIR = path.join(process.env.HOME, '.meteor'); - if (process.platform == 'win32') { - process.env.METEOR_WAREHOUSE_DIR = path.join(process.env.LOCALAPPDATA || process.env.APPDATA, '.meteor'); - } + process.env.METEOR_WAREHOUSE_DIR = env.buildFromHomePath('.meteor'); } // set our home dir so we can easily blow away meteorite installs diff --git a/spec/lib/runner.js b/spec/lib/runner.js index 986161d..a7fb829 100644 --- a/spec/lib/runner.js +++ b/spec/lib/runner.js @@ -6,9 +6,11 @@ var exec = require('child_process').exec; var _ = require('underscore'); var utils = require('./utils.js'); var wrench = require('wrench'); +var which = require('which'); var fstream = require('fstream'); -var meteoriteExecutable = path.resolve(path.join('bin', 'mrt.js')); +//var meteoriteExecutable = path.resolve(path.join('bin', 'mrt.js')); +var meteoriteExecutable = which.sync('meteorite'); var matchesSpecs = function(output, specs) { return _.all(specs, function(spec) { From b953136c285e9d72b2f073b02f950776b1fb5e73 Mon Sep 17 00:00:00 2001 From: Sean Walker Date: Thu, 23 Jan 2014 21:18:03 -0600 Subject: [PATCH 12/34] Fixed the 'which' version. --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b4ef598..d4faaf3 100644 --- a/package.json +++ b/package.json @@ -14,12 +14,13 @@ , "colors": "0.6.0-1" , "async": "0.2.9" , "rolling_timeout_exec": ">=0.0.1" - , "which": ">=1.5.5" + , "which": ">=1.0.5" } , "devDependencies": { "mocha": ">=1.2.2" , "connect": ">=2.3.6" - , "which": ">=1.5.5" + , "wrench": ">=1.5.5" + , "which": ">=1.0.5" } , "scripts": { "test": "mocha spec/unit spec/acceptance -t 240000 -R spec" From a81efd39400d06086ca9b72ac16a4c8f63aa3c90 Mon Sep 17 00:00:00 2001 From: yeputons Date: Sat, 25 Jan 2014 23:42:06 +0400 Subject: [PATCH 13/34] CONTRIBUTING.md: merged with master (looks like it haven't been for some reason) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 50d6640..3a033e2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,7 +68,7 @@ $ npm install ### 2. Git path -You'll need to ensure you have a git executable available at `/usr/local/bin/git` (see #229). You can just symlink from whereever. +You'll need to ensure you have a git executable available at your PATH so `which git` can find it. You can find out where your current git command is being executed like this: From d9eea8f49c2c66a50c00fe911153e25d0b06d3eb Mon Sep 17 00:00:00 2001 From: yeputons Date: Sat, 25 Jan 2014 23:54:57 +0400 Subject: [PATCH 14/34] #224: acceptance/test_spec.js now overrides both LOCALAPPDATA and HOME --- spec/acceptance/test_spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/acceptance/test_spec.js b/spec/acceptance/test_spec.js index 3138d2c..d1b91e0 100644 --- a/spec/acceptance/test_spec.js +++ b/spec/acceptance/test_spec.js @@ -30,6 +30,7 @@ before(function(done){ // set our home dir so we can easily blow away meteorite installs wrench.mkdirSyncRecursive(appHome); process.env.HOME = appHome; + process.env.LOCALAPPDATA = appHome; console.log("Preparing..") // ensure we have the latest dev bundle cached From c9e0049953dcc7768d97bffe05f600c99ac81b74 Mon Sep 17 00:00:00 2001 From: Egor Suvorov Date: Sun, 26 Jan 2014 00:40:59 +0400 Subject: [PATCH 15/34] spec/support/bin/git: '-T' key was added to 'cp'', because target directory is pre-created as a workaround for windows git --- spec/support/bin/git | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/support/bin/git b/spec/support/bin/git index 3ec6a3c..9ad2545 100755 --- a/spec/support/bin/git +++ b/spec/support/bin/git @@ -12,7 +12,8 @@ var command = _.first(args); var copyRepo = function(from, to) { wrench.mkdirSyncRecursive(path.dirname(to)); - spawn('cp', ['-r', from, to]); + // -T is required because 'to' directory may be already created + spawn('cp', ['-Tr', from, to]); }; var REAL_GIT = process.env._METEORITE_REAL_GIT; From 92695e08a52a445f2ecf52a88cf2c9670212652b Mon Sep 17 00:00:00 2001 From: yeputons Date: Sun, 26 Jan 2014 02:30:28 +0400 Subject: [PATCH 16/34] #224: tests: now meteoriteExecutable is calculated in /spec/lib/env.js - it's one of ./bin/mrt.{js,bat} (the latter was added) --- bin/mrt.bat | 2 ++ spec/lib/atmosphere.js | 2 +- spec/lib/env.js | 7 +++++++ spec/lib/runner.js | 5 +---- 4 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 bin/mrt.bat create mode 100644 spec/lib/env.js diff --git a/bin/mrt.bat b/bin/mrt.bat new file mode 100644 index 0000000..efa1151 --- /dev/null +++ b/bin/mrt.bat @@ -0,0 +1,2 @@ +@REM This file is required for testing purposes only +@node %~dp0\mrt.js %* diff --git a/spec/lib/atmosphere.js b/spec/lib/atmosphere.js index 7a88cff..1443623 100644 --- a/spec/lib/atmosphere.js +++ b/spec/lib/atmosphere.js @@ -6,7 +6,7 @@ var async = require('async'); var assert = require('assert'); -var baseCommand = 'meteorite --repoHost localhost --repoPort 3333 --repoUsername test --repoPassword testtest' +var baseCommand = require('./env').meteoriteExecutable + ' --repoHost localhost --repoPort 3333 --repoUsername test --repoPassword testtest' var packagesNeeded = { 'mrt-test-pkg1': ['0.1.0', '0.2.0'], diff --git a/spec/lib/env.js b/spec/lib/env.js new file mode 100644 index 0000000..e68e6fd --- /dev/null +++ b/spec/lib/env.js @@ -0,0 +1,7 @@ +var path = require('path'); + +Env = { + meteoriteExecutable: path.resolve(path.join('bin', 'mrt.' + (process.platform === 'win32' ? 'bat' : 'js'))) +}; + +module.exports = Env; diff --git a/spec/lib/runner.js b/spec/lib/runner.js index a7fb829..6a55696 100644 --- a/spec/lib/runner.js +++ b/spec/lib/runner.js @@ -9,9 +9,6 @@ var wrench = require('wrench'); var which = require('which'); var fstream = require('fstream'); -//var meteoriteExecutable = path.resolve(path.join('bin', 'mrt.js')); -var meteoriteExecutable = which.sync('meteorite'); - var matchesSpecs = function(output, specs) { return _.all(specs, function(spec) { return output.indexOf(spec) > -1; @@ -118,7 +115,7 @@ var invokeMrt = function(directory, args, options, done) { args.push('--repoHost=localhost'); args.push('--port=4444'); - spawnAndWait(meteoriteExecutable, args, options, done); + spawnAndWait(require('./env').meteoriteExecutable, args, options, done); } var invokeMrtInApp = function(appName, args, options, done) { From 6f9992e190232a0297f9004e0f1b100eb0365169 Mon Sep 17 00:00:00 2001 From: yeputons Date: Sun, 26 Jan 2014 02:58:46 +0400 Subject: [PATCH 17/34] #224: spec/support/bin: git.bat was added; git was fixed to pre-create target path before calling REAL_GIT --- spec/support/bin/git | 1 + spec/support/bin/git.bat | 1 + 2 files changed, 2 insertions(+) create mode 100644 spec/support/bin/git.bat diff --git a/spec/support/bin/git b/spec/support/bin/git index 9ad2545..b5da2d4 100755 --- a/spec/support/bin/git +++ b/spec/support/bin/git @@ -38,6 +38,7 @@ if (command === 'clone') { if (!fs.existsSync(repoCachePath)) { args.push(repoUrl); args.push(repoCachePath); + wrench.mkdirSyncRecursive(repoCachePath); var git = spawn(REAL_GIT, args); git.on('exit', function() { diff --git a/spec/support/bin/git.bat b/spec/support/bin/git.bat new file mode 100644 index 0000000..91fcb77 --- /dev/null +++ b/spec/support/bin/git.bat @@ -0,0 +1 @@ +@node %~dp0\git %* From 66f716e5d225abcadc5593e12341eb04c8279177 Mon Sep 17 00:00:00 2001 From: Egor Suvorov Date: Mon, 3 Feb 2014 20:14:56 +0400 Subject: [PATCH 18/34] #224: test_spec.js: _METEORITE_REAL_CURL is unused now, removing --- spec/acceptance/test_spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/acceptance/test_spec.js b/spec/acceptance/test_spec.js index d1b91e0..3faca09 100644 --- a/spec/acceptance/test_spec.js +++ b/spec/acceptance/test_spec.js @@ -18,7 +18,6 @@ var appDir = path.join(appHome, 'app'); before(function(done){ // ensure our "cached" git is in the path process.env._METEORITE_REAL_GIT = which.sync('git'); - process.env._METEORITE_REAL_CURL = which.sync('curl'); process.env._METEORITE_REAL_METEOR = path.basename(which.sync('meteor')); process.env.PATH = [path.resolve(path.join('spec', 'support', 'bin')), process.env.PATH].join(path.delimiter); From 8a7d558b7234315d0fbceb9dea7e4188098e27d7 Mon Sep 17 00:00:00 2001 From: Egor Suvorov Date: Mon, 3 Feb 2014 20:17:53 +0400 Subject: [PATCH 19/34] #224: tests: .bat files: quotes was added to make testing possible from directories with spaces --- bin/mrt.bat | 2 +- spec/support/bin/git.bat | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/mrt.bat b/bin/mrt.bat index efa1151..ab8ea23 100644 --- a/bin/mrt.bat +++ b/bin/mrt.bat @@ -1,2 +1,2 @@ @REM This file is required for testing purposes only -@node %~dp0\mrt.js %* +@node "%~dp0\mrt.js" %* diff --git a/spec/support/bin/git.bat b/spec/support/bin/git.bat index 91fcb77..b3a4078 100644 --- a/spec/support/bin/git.bat +++ b/spec/support/bin/git.bat @@ -1 +1 @@ -@node %~dp0\git %* +@node "%~dp0\git" %* From bafcc9dc910cf0ed23bf8ca56762af2061e47379 Mon Sep 17 00:00:00 2001 From: Egor Suvorov Date: Mon, 3 Feb 2014 20:42:03 +0400 Subject: [PATCH 20/34] #224: spec/lib/atmosphere.js: baseCommand now adds quotes around meteoriteExecutable to work OK from folders with spaces --- spec/lib/atmosphere.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/atmosphere.js b/spec/lib/atmosphere.js index 1443623..ff5fae7 100644 --- a/spec/lib/atmosphere.js +++ b/spec/lib/atmosphere.js @@ -6,7 +6,7 @@ var async = require('async'); var assert = require('assert'); -var baseCommand = require('./env').meteoriteExecutable + ' --repoHost localhost --repoPort 3333 --repoUsername test --repoPassword testtest' +var baseCommand = '"' + require('./env').meteoriteExecutable + '" --repoHost localhost --repoPort 3333 --repoUsername test --repoPassword testtest' var packagesNeeded = { 'mrt-test-pkg1': ['0.1.0', '0.2.0'], From 729ee2a2b135bcc800bc834c4c999d35e27a5cdc Mon Sep 17 00:00:00 2001 From: Egor Suvorov Date: Mon, 3 Feb 2014 23:28:18 +0400 Subject: [PATCH 21/34] #224: process.exit() was replaced by npm 'exit' package (+return), which waits till stdout/stderr buffers are flushed on Windows before exit --- lib/atmosphere.js | 16 +++++++++++----- lib/project.js | 4 +++- package.json | 1 + spec/support/bin/git | 4 +++- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lib/atmosphere.js b/lib/atmosphere.js index f36d1e9..1b8a32f 100644 --- a/lib/atmosphere.js +++ b/lib/atmosphere.js @@ -11,6 +11,7 @@ var prompt = require('prompt'); var meteoriteArgs = require('optimist').argv; var version = require('../package').version; var env = require('../lib/utils/env'); +var exit = require('exit'); var writeUserTokenFile = function(user) { var cfg = { @@ -59,7 +60,8 @@ Atmosphere = { }); } - process.exit(1); + exit(1); + return; } meteoriteArgs.verbose && console.log("Published."); fn(); @@ -164,7 +166,8 @@ Atmosphere = { console.log("Please ensure you are running the latest version of Meteorite".red); console.log(" npm install -g meteorite".red); console.log("If problems persist, please report here: http://github.com/oortcloud/meteorite/issues".red); - process.exit(1); + exit(1); + return; } meteoriteArgs.verbose && console.log("Connected.."); @@ -203,7 +206,8 @@ Atmosphere = { }, function (err, input) { if (err) { console.log('Error:', err.reason); - process.exit(1); + exit(1); + return; } meteoriteArgs.verbose && console.log("Got credentials, logging in.."); @@ -216,7 +220,8 @@ Atmosphere = { if (err) { console.log('Error:', err.reason); - process.exit(1); + exit(1); + return; } writeUserTokenFile(user); @@ -254,7 +259,8 @@ Atmosphere = { }], function(err, user) { if (err) { console.log('Error:', err.reason); - process.exit(1); + exit(1); + return; } meteoriteArgs.verbose && console.log("Logged in."); diff --git a/lib/project.js b/lib/project.js index 550129e..3922518 100644 --- a/lib/project.js +++ b/lib/project.js @@ -7,6 +7,7 @@ var Meteor = require('./meteor'); var Command = require('./command'); var wrench = require('wrench'); var exec = require('child_process').exec; +var exit = require('exit'); // The project is the current directory's personal version of meteor, // complete with its own set of packages. @@ -102,7 +103,8 @@ Project.prototype.fetch = function(fn, forceUpdate) { if (err) { console.log(err.message.red); - process.exit(1); + exit(1); + return; } fn(); diff --git a/package.json b/package.json index d4faaf3..59599f2 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ , "async": "0.2.9" , "rolling_timeout_exec": ">=0.0.1" , "which": ">=1.0.5" + , "exit": ">=0.1.2" } , "devDependencies": { "mocha": ">=1.2.2" diff --git a/spec/support/bin/git b/spec/support/bin/git index b5da2d4..1fa173e 100755 --- a/spec/support/bin/git +++ b/spec/support/bin/git @@ -5,6 +5,7 @@ var path = require('path'); var fs = require('../../../lib/utils/fs'); var wrench = require('wrench'); var _ = require('underscore'); +var exit = require('exit'); var args = process.argv.slice(2); @@ -19,7 +20,8 @@ var copyRepo = function(from, to) { var REAL_GIT = process.env._METEORITE_REAL_GIT; if (!REAL_GIT) { console.error('No _METEORITE_REAL_GIT specified'); - process.exit(1); + exit(1); + return; } if (command === 'clone') { From eb6e90f302fec2d30cfe2aa41e6bb77dbc2ea3a0 Mon Sep 17 00:00:00 2001 From: Egor Suvorov Date: Mon, 3 Feb 2014 23:38:50 +0400 Subject: [PATCH 22/34] #224: spec/support/bin/git: replaced 'cp -Tr' callby wrench.copyDirSyncRecursive --- spec/support/bin/git | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/support/bin/git b/spec/support/bin/git index 1fa173e..77cf5bd 100755 --- a/spec/support/bin/git +++ b/spec/support/bin/git @@ -13,8 +13,9 @@ var command = _.first(args); var copyRepo = function(from, to) { wrench.mkdirSyncRecursive(path.dirname(to)); - // -T is required because 'to' directory may be already created - spawn('cp', ['-Tr', from, to]); + wrench.copyDirSyncRecursive(from, to, { + forceDelete: true // Directory 'to' may already exists + }); }; var REAL_GIT = process.env._METEORITE_REAL_GIT; From 18a2a84f177554737f42a2d3efc0d7ad98c9350b Mon Sep 17 00:00:00 2001 From: Egor Suvorov Date: Tue, 4 Feb 2014 16:10:57 +0400 Subject: [PATCH 23/34] #224: bin/mrt.bat was moved to spec/support/bin/mrt.bat; spec/lib/env.js was correspondingly modified --- spec/lib/env.js | 10 ++++++++-- {bin => spec/support/bin}/mrt.bat | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) rename {bin => spec/support/bin}/mrt.bat (58%) diff --git a/spec/lib/env.js b/spec/lib/env.js index e68e6fd..e2c7acf 100644 --- a/spec/lib/env.js +++ b/spec/lib/env.js @@ -1,7 +1,13 @@ var path = require('path'); -Env = { - meteoriteExecutable: path.resolve(path.join('bin', 'mrt.' + (process.platform === 'win32' ? 'bat' : 'js'))) +if (process.platform === 'win32') { + // Slashes are automatically normalized by path.resolve on Windows + shortPath = 'spec/support/bin/mrt.bat'; +} else { + shortPath = 'bin/mrt.js'; }; +Env = { + meteoriteExecutable: path.resolve(shortPath) +} module.exports = Env; diff --git a/bin/mrt.bat b/spec/support/bin/mrt.bat similarity index 58% rename from bin/mrt.bat rename to spec/support/bin/mrt.bat index ab8ea23..40f6366 100644 --- a/bin/mrt.bat +++ b/spec/support/bin/mrt.bat @@ -1,2 +1,2 @@ @REM This file is required for testing purposes only -@node "%~dp0\mrt.js" %* +@node "%~dp0\..\..\..\bin\mrt.js" %* From 7841a32831b05dc9de5f0ce257ba2e085c3b0f77 Mon Sep 17 00:00:00 2001 From: yeputons Date: Wed, 12 Feb 2014 16:54:45 +0400 Subject: [PATCH 24/34] windows-updates: replaced require('child_process').spawn by spawn-cmd --- lib/atmosphere.js | 2 +- lib/command.js | 2 +- lib/meteor.js | 2 +- lib/sources/git.js | 2 +- package.json | 1 + spec/lib/runner.js | 2 +- spec/lib/utils.js | 2 +- spec/support/bin/git | 2 +- 8 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/atmosphere.js b/lib/atmosphere.js index 1b8a32f..7282bff 100644 --- a/lib/atmosphere.js +++ b/lib/atmosphere.js @@ -3,7 +3,7 @@ var Config = require('./config'); var path = require('path'); var fs = require('fs'); var _ = require('underscore'); -var spawn = require('child_process').spawn; +var spawn = require('spawn-cmd').spawn; var exec = require('child_process').exec; var git = require('./utils/git'); var _ = require('underscore'); diff --git a/lib/command.js b/lib/command.js index 3c97a28..7a4dbda 100644 --- a/lib/command.js +++ b/lib/command.js @@ -1,4 +1,4 @@ -var spawn = require('child_process').spawn; +var spawn = require('spawn-cmd').spawn; var exec = require('child_process').exec; var path = require('path'); var fs = require('fs'); diff --git a/lib/meteor.js b/lib/meteor.js index 20d78c4..61bc8e8 100644 --- a/lib/meteor.js +++ b/lib/meteor.js @@ -5,7 +5,7 @@ var Command = require('./command'); var fs = require('fs'); var fstream = require('fstream'); var wrench = require('wrench'); -var spawn = require('child_process').spawn; +var spawn = require('spawn-cmd').spawn; var exec = require('child_process').exec; var which = require('which'); diff --git a/lib/sources/git.js b/lib/sources/git.js index 4853a0f..7a19a51 100644 --- a/lib/sources/git.js +++ b/lib/sources/git.js @@ -3,7 +3,7 @@ var path = require('path'); var wrench = require('wrench'); var fs = require('fs'); var url = require('url'); -var spawn = require('child_process').spawn; +var spawn = require('spawn-cmd').spawn; var exec = require('rolling_timeout_exec').exec; var fstream = require('fstream'); diff --git a/package.json b/package.json index 59599f2..6560a6e 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ , "rolling_timeout_exec": ">=0.0.1" , "which": ">=1.0.5" , "exit": ">=0.1.2" + , "spawn-cmd": ">=0.0.2" } , "devDependencies": { "mocha": ">=1.2.2" diff --git a/spec/lib/runner.js b/spec/lib/runner.js index 6a55696..4ad5bc0 100644 --- a/spec/lib/runner.js +++ b/spec/lib/runner.js @@ -1,7 +1,7 @@ // run mrt against a certain app and wait for given output var path = require('path'); -var spawn = require('child_process').spawn; +var spawn = require('spawn-cmd').spawn; var exec = require('child_process').exec; var _ = require('underscore'); var utils = require('./utils.js'); diff --git a/spec/lib/utils.js b/spec/lib/utils.js index 3f85501..7bd749a 100644 --- a/spec/lib/utils.js +++ b/spec/lib/utils.js @@ -1,5 +1,5 @@ // basic filesystem utils for our tests -var spawn = require('child_process').spawn; +var spawn = require('spawn-cmd').spawn; var path = require('path'); var fs = require('fs'); var _ = require('underscore'); diff --git a/spec/support/bin/git b/spec/support/bin/git index 77cf5bd..b8a1088 100755 --- a/spec/support/bin/git +++ b/spec/support/bin/git @@ -1,6 +1,6 @@ #!/usr/bin/env node -var spawn = require('child_process').spawn; +var spawn = require('spawn-cmd').spawn; var path = require('path'); var fs = require('../../../lib/utils/fs'); var wrench = require('wrench'); From 3cd862baac638d8770936dcd28625bcc9991b3b0 Mon Sep 17 00:00:00 2001 From: yeputons Date: Wed, 12 Feb 2014 16:56:07 +0400 Subject: [PATCH 25/34] test_spec.js: removed path.basename() call from _METEORITE_REAL_METEOR initialization --- spec/acceptance/test_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/acceptance/test_spec.js b/spec/acceptance/test_spec.js index 3faca09..aed940f 100644 --- a/spec/acceptance/test_spec.js +++ b/spec/acceptance/test_spec.js @@ -18,7 +18,7 @@ var appDir = path.join(appHome, 'app'); before(function(done){ // ensure our "cached" git is in the path process.env._METEORITE_REAL_GIT = which.sync('git'); - process.env._METEORITE_REAL_METEOR = path.basename(which.sync('meteor')); + process.env._METEORITE_REAL_METEOR = which.sync('meteor'); process.env.PATH = [path.resolve(path.join('spec', 'support', 'bin')), process.env.PATH].join(path.delimiter); if (!process.env.METEOR_WAREHOUSE_DIR) { From e3ad246d209af6a2c973170b4bd71d4fe9a87c93 Mon Sep 17 00:00:00 2001 From: yeputons Date: Wed, 12 Feb 2014 16:59:08 +0400 Subject: [PATCH 26/34] windows-updated: removed temporary Meteor.prototype._executable() which added '.bat' to 'meteor' command before spawn-cmd --- lib/meteor.js | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/lib/meteor.js b/lib/meteor.js index 61bc8e8..b2c6a3c 100644 --- a/lib/meteor.js +++ b/lib/meteor.js @@ -97,7 +97,6 @@ Meteor.prototype.ensurePrepared = function(fn) { } }; -/* // Saving the original function so we can revert quickly once spawn-cmd is in place. Meteor.prototype._executable = function() { var self = this; @@ -108,19 +107,6 @@ Meteor.prototype._executable = function() { return path.join(self.source.packagePath(), 'meteor'); } } -*/ - -// Temporary code to be ripped out once spawn-cmd is in place. -Meteor.prototype._executable = function() { - var self = this; - var executableName = path.basename(which.sync('meteor')); - - if (self.defaultMeteor) { - return executableName; - } else { - return path.join(self.source.packagePath(), executableName); - } -} // run a command using just this checked-out version of meteor Meteor.prototype.execute = function(args, package_dir, fn) { From 84b77c94252ea1c8d7ee1ff8b31be15d923cb281 Mon Sep 17 00:00:00 2001 From: yeputons Date: Wed, 12 Feb 2014 21:47:22 +0400 Subject: [PATCH 27/34] windows-updates: lib/meteor.js some outdated comments were removed --- lib/meteor.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/meteor.js b/lib/meteor.js index b2c6a3c..0d2e208 100644 --- a/lib/meteor.js +++ b/lib/meteor.js @@ -76,7 +76,6 @@ Meteor.prototype.install = function(buildDevBundle, fn) { } else { // meteor --help installs the dev bundle before doing anything else console.log('Downloading Meteor development bundle'); - //var meteor = spawn('./meteor', ['--help'], {cwd: self.source.path}); var meteor = spawn(self._executable(), ['--help'], {cwd: self.source.path}); // just output the status bar @@ -97,7 +96,6 @@ Meteor.prototype.ensurePrepared = function(fn) { } }; -// Saving the original function so we can revert quickly once spawn-cmd is in place. Meteor.prototype._executable = function() { var self = this; From 5f29f6f26df164d0263ab47d4073081b0f988c31 Mon Sep 17 00:00:00 2001 From: yeputons Date: Fri, 14 Feb 2014 18:35:00 +0400 Subject: [PATCH 28/34] windows-updates: lib/meteor.js: forced defaultMeteor on Windows --- lib/meteor.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/meteor.js b/lib/meteor.js index 0d2e208..1e7006d 100644 --- a/lib/meteor.js +++ b/lib/meteor.js @@ -9,6 +9,7 @@ var spawn = require('spawn-cmd').spawn; var exec = require('child_process').exec; var which = require('which'); +var customMeteorWarning = false; // A 'Meteor' refers to a single commit (branch, tag) of a version of the core meteor // @@ -19,6 +20,15 @@ Meteor = function(config) { // Config defaults config = config || {}; this.defaultMeteor = (! _.include(_.keys(config), 'git')); + + if (!this.defaultMeteor && !config['force-on-windows'] && process.platform == 'win32') { + if (!customMeteorWarning) { + console.log('Custom Meteor build most probably won\' work on Windows, using default instead'.red.bold); + console.log('Please refer to the README.md for details'.red.bold); + customMeteorWarning = true; + } + this.defaultMeteor = true; + } if (this.defaultMeteor) { this.prepared = true From 099aab24869c8f4ae0447c9697f09bfd720983b5 Mon Sep 17 00:00:00 2001 From: yeputons Date: Fri, 14 Feb 2014 18:37:02 +0400 Subject: [PATCH 29/34] windows-updates: README.txt was added with information about Meteor pinning --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index eda4567..1febcf5 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,8 @@ Meteorite writes to a `smart.lock` file in the app's root directory to track the The `meteor` property is not required: apps will depend on Meteor's master branch by default. You can specify `meteor.branch`, `meteor.tag` or `meteor.git` to use alternate branches, tags and forks respectively. Note that `meteor.git` expects an actual URL, use `ssh://git@github.com/meteor/meteor.git` instead of `git@github.com:meteor/meteor.git`. +Keep in mind that main Meteor repository doesn't work well on Windows yet and Meteor pinning is explicitly disabled for Windows users of Meteorite (default Meteor is always used). If you still want Meteorite to run your custom Meteor that works both on Windows and Linux, add `meteor.force-on-windows: true` parameter to `smart.json`. + ``` json { "packages": { From 7f4cacaba2f3b863229db8ddfeb74bd91194e679 Mon Sep 17 00:00:00 2001 From: yeputons Date: Fri, 14 Feb 2014 18:50:41 +0400 Subject: [PATCH 30/34] windows-updates: disabled Meteor pinning tests on Windows --- spec/acceptance/run_spec.js | 40 ++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/spec/acceptance/run_spec.js b/spec/acceptance/run_spec.js index cf24e02..b408e3a 100644 --- a/spec/acceptance/run_spec.js +++ b/spec/acceptance/run_spec.js @@ -104,29 +104,33 @@ describe('invoking `mrt run`', function() { }); }); - describe('and the smart.json specifies a meteor fork pinned to a branch', function() { - it("should run the forked meteor checked out to the branch", function(done) { - runner.invokeMrtInApp('app-with-meteor-pinned-to-branch', ['run'], { - waitForOutput: "Meteor is instrumented for meteorite test (branch/mrt-branch-test)" - }, done); + if (process.platform == 'win32') { + console.log('Skipping Meteor pinning tests because this is not expected to work on Windows'.yellow.bold); + } else { + describe('and the smart.json specifies a meteor fork pinned to a branch', function() { + it("should run the forked meteor checked out to the branch", function(done) { + runner.invokeMrtInApp('app-with-meteor-pinned-to-branch', ['run'], { + waitForOutput: "Meteor is instrumented for meteorite test (branch/mrt-branch-test)" + }, done); + }); }); - }); - describe('and the smart.json specifies a meteor fork pinned to a tag', function() { - it("should run the forked meteor checked out to the branch", function(done) { - runner.invokeMrtInApp('app-with-meteor-pinned-to-tag', ['run'], { - waitForOutput: "Meteor is instrumented for meteorite test (tag/mrt-test-tag)" - }, done); + describe('and the smart.json specifies a meteor fork pinned to a tag', function() { + it("should run the forked meteor checked out to the branch", function(done) { + runner.invokeMrtInApp('app-with-meteor-pinned-to-tag', ['run'], { + waitForOutput: "Meteor is instrumented for meteorite test (tag/mrt-test-tag)" + }, done); + }); }); - }); - describe('and the smart.json specifies a meteor fork pinned to a ref', function() { - it("should run the forked meteor checked out to the branch", function(done) { - runner.invokeMrtInApp('app-with-meteor-pinned-to-ref', ['run'], { - waitForOutput: "Meteor is instrumented for meteorite test (ref)" - }, done); + describe('and the smart.json specifies a meteor fork pinned to a ref', function() { + it("should run the forked meteor checked out to the branch", function(done) { + runner.invokeMrtInApp('app-with-meteor-pinned-to-ref', ['run'], { + waitForOutput: "Meteor is instrumented for meteorite test (ref)" + }, done); + }); }); - }); + } }); }); From 906f56adef8f8b6247e1475a5dac95ca14a0553f Mon Sep 17 00:00:00 2001 From: yeputons Date: Fri, 14 Feb 2014 19:36:42 +0400 Subject: [PATCH 31/34] windows-updates: added detectEol() and its calls when writing to smart.json, smart.lock and .gitignore - original EOL is used or os.EOL of there were no such file --- lib/dependencies/package.js | 6 ++++-- lib/eol.js | 21 +++++++++++++++++++++ lib/project.js | 7 +++++-- 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 lib/eol.js diff --git a/lib/dependencies/package.js b/lib/dependencies/package.js index 3fa1689..217de2a 100755 --- a/lib/dependencies/package.js +++ b/lib/dependencies/package.js @@ -2,6 +2,7 @@ var _ = require('underscore'); var path = require('path'); var fs = require('fs'); var Source = require('../sources/source'); +var detectEol = require('../eol').detectEol; // A package represents a single version of a single package // @@ -152,13 +153,14 @@ Package.prototype.addToGitIgnore = function(project) { if (fs.existsSync(gitignorePath)) gitignoreContent = fs.readFileSync(gitignorePath, 'utf8'); - var lines = gitignoreContent.split('\n'); + var eol = detectEol(gitignoreContent); + var lines = gitignoreContent.split(eol); if (! _.any(lines, function(l) { return l === "/" + self.name })) { lines.push("/" + self.name); lines = _.filter(lines, function(l) { return l !== ''}); - gitignoreContent = lines.join('\n') + '\n'; + gitignoreContent = lines.join(eol) + eol; fs.writeFileSync(gitignorePath, gitignoreContent); } } diff --git a/lib/eol.js b/lib/eol.js new file mode 100644 index 0000000..22fbe61 --- /dev/null +++ b/lib/eol.js @@ -0,0 +1,21 @@ +var os = require('os'); + +// Users may have UNIX line endings on Windows if their git is configured +// in that way, see https://github.com/oortcloud/meteorite/pull/224#issuecomment-34903926 +eol = { + detectEol: function(data) { + data = data || ''; + var eols = [ '\r\n', '\r', '\n' ]; + var result = os.EOL; + for (var i = 0; i < eols.length; i++) { + var eol = eols[i]; + if (data.indexOf(eol) >= 0) { + result = eol; + break; + } + }; + return result; + } +} + +module.exports = eol; diff --git a/lib/project.js b/lib/project.js index 3922518..f83099e 100644 --- a/lib/project.js +++ b/lib/project.js @@ -8,6 +8,7 @@ var Command = require('./command'); var wrench = require('wrench'); var exec = require('child_process').exec; var exit = require('exit'); +var detectEol = require('./eol').detectEol; // The project is the current directory's personal version of meteor, // complete with its own set of packages. @@ -21,6 +22,7 @@ Project = function(root, meteorArgs) { this.smartJsonPath = path.join(this.root, 'smart.json'); this.smartLockPath = path.join(this.root, 'smart.lock'); this.packagesRoot = path.join(this.root, 'packages'); + this.EOL = detectEol(); // set a base meteor if it's specified in the args (or a default one if not) this.meteor = new Meteor(meteorArgs); @@ -43,6 +45,7 @@ Project.prototype.initFromLock = function() { pkg.root = self.root; }); + this.EOL = detectEol(data); this.meteor = new Meteor(lockData.meteor); this.dependencies = Dependencies.newFromLockJson(lockData.dependencies); } @@ -321,7 +324,7 @@ Project.prototype.writeSmartJson = function(json) { // Write to disk if (fs.existsSync(this.root)) - fs.writeFileSync(this.smartJsonPath, smartJsonString); + fs.writeFileSync(this.smartJsonPath, smartJsonString.replace(/\n/g, this.EOL)); }; Project.prototype.lockJson = function() { @@ -336,7 +339,7 @@ Project.prototype.lockJson = function() { Project.prototype.writeLockFile = function() { var smartJsonString = JSON.stringify(this.lockJson(), null, 2) + "\n"; - fs.writeFileSync(this.smartLockPath, smartJsonString); + fs.writeFileSync(this.smartLockPath, smartJsonString.replace(/\n/g, this.EOL)); }; Project.prototype._optimizeFS = function() { From dd7068e4f60f610dff127a64f53e25e8688930eb Mon Sep 17 00:00:00 2001 From: yeputons Date: Fri, 14 Feb 2014 19:38:35 +0400 Subject: [PATCH 32/34] windows-updates: now 'create-package' command uses os.EOL for stub files instead of '\n' --- lib/meteorite.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/meteorite.js b/lib/meteorite.js index 6fd7875..a68a7cb 100644 --- a/lib/meteorite.js +++ b/lib/meteorite.js @@ -5,6 +5,7 @@ var fs = require('fs'); var _ = require('underscore'); var wrench = require('wrench'); var env = require('../lib/utils/env'); +var os = require('os'); Meteorite = function(args, meteorArgs) { this.args = args; @@ -57,7 +58,7 @@ Meteorite.prototype['create-package'] = function(fn) { // write package.js fs.writeFileSync(path.join(packageDir, 'package.js'), - 'Package.describe({\n' + + ('Package.describe({\n' + ' summary: "REPLACEME - What does this package (or the original one you\'re wrapping) do?"\n' + '});\n\n' + 'Package.on_use(function (api, where) {\n' + @@ -67,13 +68,15 @@ Meteorite.prototype['create-package'] = function(fn) { ' api.use(\'' + packageName + '\');\n\n' + ' api.add_files(\'' + testFile + '\', [\'client\', \'server\']);\n' + '});\n' + ).replace(/\n/g, os.EOL) ); // touch relevant files fs.writeFileSync(path.join(packageDir, packageFile), ''); fs.writeFileSync(path.join(packageDir, testFile), - '// See https://github.com/dandv/meteor-crypto-base64/blob/master/crypto-base64_tests.js for a simple example' + - '// See https://www.eventedmind.com/feed/e6gJZXNQWyNP2MLsb for more on testing with Tinytest' + ('// See https://github.com/dandv/meteor-crypto-base64/blob/master/crypto-base64_tests.js for a simple example\n' + + '// See https://www.eventedmind.com/feed/e6gJZXNQWyNP2MLsb for more on testing with Tinytest\n' + ).replace(/\n/g, os.EOL) ); // write simple smart.json @@ -85,7 +88,7 @@ Meteorite.prototype['create-package'] = function(fn) { "version": "0.0.1", "git": "", "packages": {} - }, null, 2)); + }, null, 2).replace(/\n/g, os.EOL)); } // XXX: this should probably track this (so further calls to mrt install From 0ead4d39be43a5c0874dff86e3e15daa7202a6a5 Mon Sep 17 00:00:00 2001 From: yeputons Date: Fri, 14 Feb 2014 19:51:09 +0400 Subject: [PATCH 33/34] windows-updates: EOL heuristics: now it's run once, in Project's constructor and reads both smart.lock and smart.json --- lib/project.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/project.js b/lib/project.js index f83099e..d3badf6 100644 --- a/lib/project.js +++ b/lib/project.js @@ -22,7 +22,13 @@ Project = function(root, meteorArgs) { this.smartJsonPath = path.join(this.root, 'smart.json'); this.smartLockPath = path.join(this.root, 'smart.lock'); this.packagesRoot = path.join(this.root, 'packages'); - this.EOL = detectEol(); + + var data = ''; + if (fs.existsSync(this.smartLockPath)) + data += fs.readFileSync(this.smartLockPath).toString(); + if (fs.existsSync(this.smartJsonPath)) + data += fs.readFileSync(this.smartJsonPath).toString(); + this.EOL = detectEol(data); // set a base meteor if it's specified in the args (or a default one if not) this.meteor = new Meteor(meteorArgs); @@ -45,7 +51,6 @@ Project.prototype.initFromLock = function() { pkg.root = self.root; }); - this.EOL = detectEol(data); this.meteor = new Meteor(lockData.meteor); this.dependencies = Dependencies.newFromLockJson(lockData.dependencies); } From a46be827a20edec23ecad35a880747152f3041c1 Mon Sep 17 00:00:00 2001 From: yeputons Date: Wed, 26 Mar 2014 21:53:30 +0400 Subject: [PATCH 34/34] windows-updates: README.md was updated with information about Meteorite on Windows and the new 'meteorite' command --- README.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1febcf5..a065497 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ Meteorite is a Meteor version manager and package manager. It provides an easy way to run different versions of meteor, use non-core packages, and to install packages from the [Atmosphere package repository](https://atmosphere.meteor.com/). -Meteorite provides the command `mrt`, which can be used to add and install smart packages from atmosphere. +Meteorite provides two commands: `mrt` and `meteorite` (the latter was added to avoid naming conflict with Microsoft Malicious Software Removal Tool on Windows), which can be used to add and install smart packages from atmosphere. +These commands are absolutely identical, but if you're going to call Meteorite from your scripts, you'd better use `meteorite`, as it works both on Windows and Linux. ``` sh # Create an app based on Meteor's devel branch. @@ -37,11 +38,21 @@ Subsequently, you can simply use `meteor` to run your development server, and ju ### NOTES -- Meteor is not officially supported on windows; you can run it thanks to [Tom Wijman's excellent work](http://win.meteor.com). However, meteorite's git based approach runs counter to the MSI installation that's required to get it working. So meteorite *does not* work under windows right now. Pull Requests which change this would be gladly accepted! Also, see [this blog post](http://www.discovermeteor.com/2013/03/20/using-meteor-and-atmopshere-on-windows/) for some information about how to use it. - - You'll also need to ensure you have [git](http://git-scm.com) installed and available in your path. Also, you'll need to make sure that `mrt`'s install location (usually `/usr/local/bin/`) is on your path. +### Meteorite on Windows + +Meteor is not officially supported on windows; you can run it thanks to [Tom Wijman's excellent work](http://win.meteor.com). + +Meteorite can be installed and run as any NPM package. Several things are useful to know: + +- Meteor release pinning does not work on Windows, see example below for details. +- Meteorite keeps its files under `\AppData\Local\.meteorite`, just like Meteor do. +- Directory junctions are used as the best alternative to Linux's symlinks. This automatically implies that Meteorite won't work on FAT32 drives (but will on NTFS). +- Explorer in older Windows and another file managers may handle removal of directory junctions inaccurate, which may lead to deletion of all files inside the junction instead of just +breaking the link. Please be careful: if this happens, you will have to manually remove empty package folder from Meteorite's cache to make it re-download all files. + ## Usage ### `mrt add `