Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows updates: seconds attempt #248

Open
wants to merge 38 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
bd7c019
Updated paths, added meteorite alias, addressed the HOME env with HOM…
seanmwalker Jan 20, 2014
5c7e5b5
#224: spec/acceptance/test_spec.js: ':' --> path.delimiter
yeputons Jan 20, 2014
8fde22d
#224: test_spec.js: METEOR_WAREHOUSE_DIR issue on win32 was fixed plu…
yeputons Jan 20, 2014
5f3ce28
#224: `mrt install` was fixed: symlinkSync('junction') is used
yeputons Jan 20, 2014
2463d5f
#224: spec/lib/runner.js: killProcessFamily() now works on Windows (…
yeputons Jan 20, 2014
b7367f2
#224: now folders are pre-created before 'git clone', git on Windows …
yeputons Jan 20, 2014
2145236
Updating the home env building to support a few alternative situation…
seanmwalker Jan 21, 2014
127805a
Moved the seting of path to the bottom.
seanmwalker Jan 21, 2014
91a2dd7
#224: smart_lock_spec.js test were fixed (forward/back slashes mess)
yeputons Jan 21, 2014
a48f004
#224: resolver_spec.js: absolute paths were passes through path.resol…
yeputons Jan 21, 2014
45623a6
Merge branch 'master' into windows-updates
seanmwalker Jan 22, 2014
4e06c99
Refactored how we get the windows vs linux paths, this approach makes…
seanmwalker Jan 22, 2014
b953136
Fixed the 'which' version.
Jan 24, 2014
decf301
Merge branch 'master' into windows-updates
yeputons Jan 25, 2014
a81efd3
CONTRIBUTING.md: merged with master (looks like it haven't been for s…
yeputons Jan 25, 2014
d9eea8f
#224: acceptance/test_spec.js now overrides both LOCALAPPDATA and HOME
yeputons Jan 25, 2014
c9e0049
spec/support/bin/git: '-T' key was added to 'cp'', because target dir…
yeputons Jan 25, 2014
92695e0
#224: tests: now meteoriteExecutable is calculated in /spec/lib/env.j…
yeputons Jan 25, 2014
6f9992e
#224: spec/support/bin: git.bat was added; git was fixed to pre-creat…
yeputons Jan 25, 2014
8ccf78f
Merge branch 'master' into windows-updates
yeputons Feb 3, 2014
66f716e
#224: test_spec.js: _METEORITE_REAL_CURL is unused now, removing
yeputons Feb 3, 2014
8a7d558
#224: tests: .bat files: quotes was added to make testing possible fr…
yeputons Feb 3, 2014
bafcc9d
#224: spec/lib/atmosphere.js: baseCommand now adds quotes around mete…
yeputons Feb 3, 2014
729ee2a
#224: process.exit() was replaced by npm 'exit' package (+return), wh…
yeputons Feb 3, 2014
eb6e90f
#224: spec/support/bin/git: replaced 'cp -Tr' callby wrench.copyDirSy…
yeputons Feb 3, 2014
18a2a84
#224: bin/mrt.bat was moved to spec/support/bin/mrt.bat; spec/lib/env…
yeputons Feb 4, 2014
7841a32
windows-updates: replaced require('child_process').spawn by spawn-cmd
yeputons Feb 12, 2014
3cd862b
test_spec.js: removed path.basename() call from _METEORITE_REAL_METEO…
yeputons Feb 12, 2014
e3ad246
windows-updated: removed temporary Meteor.prototype._executable() whi…
yeputons Feb 12, 2014
84b77c9
windows-updates: lib/meteor.js some outdated comments were removed
yeputons Feb 12, 2014
5f29f6f
windows-updates: lib/meteor.js: forced defaultMeteor on Windows
yeputons Feb 14, 2014
099aab2
windows-updates: README.txt was added with information about Meteor p…
yeputons Feb 14, 2014
7f4caca
windows-updates: disabled Meteor pinning tests on Windows
yeputons Feb 14, 2014
906f56a
windows-updates: added detectEol() and its calls when writing to smar…
yeputons Feb 14, 2014
dd7068e
windows-updates: now 'create-package' command uses os.EOL for stub fi…
yeputons Feb 14, 2014
0ead4d3
windows-updates: EOL heuristics: now it's run once, in Project's cons…
yeputons Feb 14, 2014
a2ec8de
Merge branch 'master' into windows-updates
yeputons Mar 26, 2014
a46be82
windows-updates: README.md was updated with information about Meteori…
yeputons Mar 26, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 `<your user>\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 <package>`
Expand Down Expand Up @@ -146,6 +157,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://[email protected]/meteor/meteor.git` instead of `[email protected]: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": {
Expand Down
24 changes: 16 additions & 8 deletions lib/atmosphere.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,29 @@ 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');
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 = {
user: user
};
var filePath = path.join(process.env.HOME, '.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, '.mrt.cfg');
var filePath = env.buildFromHomePath('.mrt.cfg');

var fileContents = fs.readFileSync(filePath);
return JSON.parse(fileContents);
Expand Down Expand Up @@ -57,7 +60,8 @@ Atmosphere = {
});
}

process.exit(1);
exit(1);
return;
}
meteoriteArgs.verbose && console.log("Published.");
fn();
Expand Down Expand Up @@ -179,7 +183,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..");
Expand Down Expand Up @@ -218,7 +223,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..");
Expand All @@ -231,7 +237,8 @@ Atmosphere = {

if (err) {
console.log('Error:', err.reason);
process.exit(1);
exit(1);
return;
}

writeUserTokenFile(user);
Expand Down Expand Up @@ -269,7 +276,8 @@ Atmosphere = {
}], function(err, user) {
if (err) {
console.log('Error:', err.reason);
process.exit(1);
exit(1);
return;
}

meteoriteArgs.verbose && console.log("Logged in.");
Expand Down
2 changes: 1 addition & 1 deletion lib/command.js
Original file line number Diff line number Diff line change
@@ -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');
Expand Down
9 changes: 6 additions & 3 deletions lib/dependencies/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
//
Expand Down Expand Up @@ -126,7 +127,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) {
Expand All @@ -151,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);
}
}
Expand Down
21 changes: 21 additions & 0 deletions lib/eol.js
Original file line number Diff line number Diff line change
@@ -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;
17 changes: 14 additions & 3 deletions lib/meteor.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ 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');

var customMeteorWarning = false;

// A 'Meteor' refers to a single commit (branch, tag) of a version of the core meteor
//
Expand All @@ -18,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
Expand Down Expand Up @@ -79,7 +90,7 @@ 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
meteor.stderr.pipe(process.stderr);
Expand Down Expand Up @@ -149,7 +160,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) {
if (error) {
throw "Error running a command: " + error;
}
Expand Down
20 changes: 12 additions & 8 deletions lib/meteorite.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ var Atmosphere = require('../lib/atmosphere');
var fs = require('fs');
var _ = require('underscore');
var wrench = require('wrench');
var env = require('../lib/utils/env');
var os = require('os');

var OUR_ARGS = ['--verbose', '--repoHost', '--repoPort', '--build-dev-bundle'];

Expand Down Expand Up @@ -63,7 +65,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' +
Expand All @@ -73,13 +75,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
Expand All @@ -91,7 +95,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
Expand All @@ -114,9 +118,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
Expand Down Expand Up @@ -236,8 +241,7 @@ _.each([
// Class methods

Meteorite.root = function() {
var homeDir = process.env.HOME;
return path.join(homeDir, '.meteorite');
return env.buildFromHomePath('.meteorite');
};

// Creates the path to ~/.meteorite
Expand Down
16 changes: 13 additions & 3 deletions lib/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ var Meteor = require('./meteor');
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.
Expand All @@ -20,6 +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');

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);
Expand Down Expand Up @@ -102,7 +111,8 @@ Project.prototype.fetch = function(fn, forceUpdate) {

if (err) {
console.log(err.message.red);
process.exit(1);
exit(1);
return;
}

fn();
Expand Down Expand Up @@ -319,7 +329,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() {
Expand All @@ -334,7 +344,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() {
Expand Down
3 changes: 2 additions & 1 deletion lib/sources/git.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -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);
Expand Down
13 changes: 13 additions & 0 deletions lib/utils/env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var path = require('path');

Env = {
buildFromHomePath: function(subPath) {
var homeDir = process.env.HOME
if (process.platform == 'win32') {
var homeDir = process.env.LOCALAPPDATA || process.env.APPDATA;
}
return path.join(homeDir, subPath);
}
};

module.exports = Env;
Loading