Initial commit (a clone of the jsmachines project as of v1.15.3)

This commit is contained in:
jeffpar 2014-09-27 14:52:57 -07:00
commit a5e3e6a59d
714 changed files with 130602 additions and 0 deletions

View file

@ -0,0 +1,3 @@
node_modules
npm-debug.log
tmp

View file

@ -0,0 +1,13 @@
{
"curly": true,
"eqeqeq": true,
"immed": true,
"latedef": true,
"newcap": true,
"noarg": true,
"sub": true,
"undef": true,
"boss": true,
"eqnull": true,
"node": true
}

View file

@ -0,0 +1,73 @@
/*
* grunt-manifester
* https://github.com/jeffpar/jsmachines
*
* Copyright (c) 2014 jeffpar
* Licensed under the MIT license.
*/
'use strict';
module.exports = function (grunt) {
// Project configuration.
grunt.initConfig({
jshint: {
all: [
'Gruntfile.js',
'tasks/*.js',
'<%= nodeunit.tests %>'
],
options: {
jshintrc: '.jshintrc'
}
},
// Before generating any new files, remove any previously-created files.
clean: {
tests: ['tmp']
},
// Configuration to be run (and then tested).
manifester: {
default_options: {
options: {
},
files: {
'tmp/default_options': ['test/fixtures/testing', 'test/fixtures/123']
}
},
custom_options: {
options: {
separator: ': ',
punctuation: ' !!!'
},
files: {
'tmp/custom_options': ['test/fixtures/testing', 'test/fixtures/123']
}
}
},
// Unit tests.
nodeunit: {
tests: ['test/*_test.js']
}
});
// Actually load this plugin's task(s).
grunt.loadTasks('tasks');
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-nodeunit');
// Whenever the "test" task is run, first clean the "tmp" dir, then run this
// plugin's task(s), then test the result.
grunt.registerTask('test', ['clean', 'manifester', 'nodeunit']);
// By default, lint and run all tests.
grunt.registerTask('default', ['jshint', 'test']);
};

View file

@ -0,0 +1,22 @@
Copyright (c) 2014 jeffpar
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,89 @@
# grunt-manifester
> manifest.xml processor
## Getting Started
This plugin requires Grunt `~0.4.4`
If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:
```shell
npm install grunt-manifester --save-dev
```
Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:
```js
grunt.loadNpmTasks('grunt-manifester');
```
## The "manifester" task
### Overview
In your project's Gruntfile, add a section named `manifester` to the data object passed into `grunt.initConfig()`.
```js
grunt.initConfig({
manifester: {
options: {
// Task-specific options go here.
},
your_target: {
// Target-specific file lists and/or options go here.
},
},
});
```
### Options
#### options.separator
Type: `String`
Default value: `', '`
A string value that is used to do something with whatever.
#### options.punctuation
Type: `String`
Default value: `'.'`
A string value that is used to do something else with whatever else.
### Usage Examples
#### Default Options
In this example, the default options are used to do something with whatever. So if the `testing` file has the content `Testing` and the `123` file had the content `1 2 3`, the generated result would be `Testing, 1 2 3.`
```js
grunt.initConfig({
manifester: {
options: {},
files: {
'dest/default_options': ['src/testing', 'src/123'],
},
},
});
```
#### Custom Options
In this example, custom options are used to do something else with whatever else. So if the `testing` file has the content `Testing` and the `123` file had the content `1 2 3`, the generated result in this case would be `Testing: 1 2 3 !!!`
```js
grunt.initConfig({
manifester: {
options: {
separator: ': ',
punctuation: ' !!!',
},
files: {
'dest/default_options': ['src/testing', 'src/123'],
},
},
});
```
## Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).
## Release History
_(Nothing yet)_

View file

@ -0,0 +1,41 @@
{
"name": "grunt-manifester",
"description": "manifest.xml processor",
"version": "0.1.0",
"homepage": "https://github.com/jeffpar/jsmachines",
"author": {
"name": "jeffpar",
"email": "jeffpar@mac.com"
},
"repository": {
"type": "git",
"url": "git://github.com/jeffpar/jsmachines.git"
},
"bugs": {
"url": "https://github.com/jeffpar/jsmachines/issues"
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/jeffpar/jsmachines/blob/master/LICENSE-MIT"
}
],
"engines": {
"node": ">= 0.8.0"
},
"scripts": {
"test": "grunt test"
},
"devDependencies": {
"grunt-contrib-jshint": "~0.6.0",
"grunt-contrib-clean": "~0.4.0",
"grunt-contrib-nodeunit": "~0.2.0",
"grunt": "~0.4.4"
},
"peerDependencies": {
"grunt": "~0.4.4"
},
"keywords": [
"gruntplugin"
]
}

View file

@ -0,0 +1,134 @@
/**
* grunt-manifester
* https://github.com/jeffpar/jsmachines
*
* Copyright (c) 2014 jeffpar
* Licensed under the MIT license.
*
* TODO: Update this header with our standard header and fix all the JSHint warnings
*/
"use strict";
var fs = require("fs");
var path = require("path");
var mkdirp = require("mkdirp");
var url = require("url");
var async = require("async");
var parseXML = require("xml2js").parseString; // see: https://github.com/Leonidas-from-XIV/node-xml2js
var unzip = require("unzip");
var util = require("util");
var net = require("../../../shared/lib/netlib");
module.exports = function (grunt) {
/*
* Please see the Grunt documentation for more information regarding task
* creation: http://gruntjs.com/creating-tasks
*/
grunt.registerMultiTask('manifester', 'manifest.xml processor', function() {
/*
* Merge task-specific and/or target-specific options with these defaults
*
var options = this.options({
});
*/
/*
* Tell grunt this task is asynchronous
*/
var asManifests = [];
var doneGrunt = this.async();
/*
* Iterate over all specified file groups
*/
this.files.forEach(function(file) {
file.src.filter(function(sFilePath) {
/*
* Warn on and remove invalid source files (if nonull was set)
*/
if (!grunt.file.exists(sFilePath)) {
grunt.log.warn('Source file "' + sFilePath + '" not found.');
return false;
}
return true;
}).map(function(sFilePath) {
/*
* TODO: Given the memory constraints I've run into with Grunt in the past, it would
* probably be better queue up the file paths instead of the file contents, and do async
* readFile() calls.
*/
asManifests.push(sFilePath);
});
});
async.each(asManifests, function processXML(sManifestFile, doneAsync) {
var sManifestXML = grunt.file.read(sManifestFile);
parseXML(sManifestXML, function doneParseXML(err, xml) {
var cCallbacks = 0;
if (xml.manifest) {
// console.log(util.inspect(xml, false, null));
for (var iRepo in xml.manifest.repo) {
var repo = xml.manifest.repo[iRepo];
if (repo.src) {
var src = repo.src[0];
var sURL = src.$['href'];
// var sURL = src._ || src; // the former is set if there are any attributes, otherwise the element is just a string
console.log('found src URL: "' + sURL + '"');
if (sURL.slice(0, 5) == "http:" && sURL.slice(-1) == '/') {
for (var iDownload in repo.download) {
var download = repo.download[iDownload];
var sDownloadFile = download.$['href'];
// var sDownloadFile = download._ || download;
console.log("processing download " + sDownloadFile);
var sRemoteFile = sURL + sDownloadFile;
var sLocalDir = path.join(path.dirname(sManifestFile), repo.$['dir']);
if (grunt.file.exists(sLocalDir) || mkdirp.sync(sLocalDir)) {
var sLocalFile = path.join(sLocalDir, sDownloadFile);
if (grunt.file.exists(sLocalFile)) {
console.log("file already exists: " + sLocalFile);
} else {
console.log('downloadFile("' + sRemoteFile + '", "' + sLocalFile + '")...');
cCallbacks++;
net.downloadFile(sRemoteFile, sLocalFile, function doneDownloadFile(err, status) {
console.log('downloadFile("' + sRemoteFile + '") returned ' + status + ': ' + (err? false : true));
if (!err && status == 200 && sLocalFile.slice(-4) == ".zip") {
var sLocalZipDir = path.join(sLocalDir, path.basename(sLocalFile, ".zip"));
if (grunt.file.exists(sLocalZipDir) || mkdirp.sync(sLocalZipDir)) {
/*
* TODO: As explained here (https://github.com/EvanOxfeld/node-unzip/issues/40), determine why this ZIP
* file (http://beej.us/moria/files/pc/zip-arc/mor55-88.zip) causes an "invalid stored block lengths" error.
*/
fs.createReadStream(sLocalFile).pipe(unzip.Extract({path: sLocalZipDir})).on('close', function() {
console.log("unzip complete: " + sLocalZipDir);
if (--cCallbacks == 0) doneAsync();
});
return;
} else {
grunt.log.warn("unzip directory not available: " + sLocalZipDir);
}
}
if (--cCallbacks == 0) doneAsync();
});
}
} else {
grunt.log.warn("download directory not available: " + sLocalDir);
}
}
} else {
grunt.log.warn("unsupported repo src: " + sURL);
}
}
}
}
if (!cCallbacks) doneAsync();
});
}, function(err) {
doneGrunt();
});
});
};

View file

@ -0,0 +1 @@
Testing: 1 2 3 !!!

View file

@ -0,0 +1 @@
Testing, 1 2 3.

View file

@ -0,0 +1 @@
1 2 3

View file

@ -0,0 +1 @@
Testing

View file

@ -0,0 +1,48 @@
'use strict';
var grunt = require('grunt');
/*
======== A Handy Little Nodeunit Reference ========
https://github.com/caolan/nodeunit
Test methods:
test.expect(numAssertions)
test.done()
Test assertions:
test.ok(value, [message])
test.equal(actual, expected, [message])
test.notEqual(actual, expected, [message])
test.deepEqual(actual, expected, [message])
test.notDeepEqual(actual, expected, [message])
test.strictEqual(actual, expected, [message])
test.notStrictEqual(actual, expected, [message])
test.throws(block, [error], [message])
test.doesNotThrow(block, [error], [message])
test.ifError(value)
*/
exports.manifester = {
setUp: function(done) {
// setup here if necessary
done();
},
default_options: function(test) {
test.expect(1);
var actual = grunt.file.read('tmp/default_options');
var expected = grunt.file.read('test/expected/default_options');
test.equal(actual, expected, 'should describe what the default behavior is.');
test.done();
},
custom_options: function(test) {
test.expect(1);
var actual = grunt.file.read('tmp/custom_options');
var expected = grunt.file.read('test/expected/custom_options');
test.equal(actual, expected, 'should describe what the custom option(s) behavior is.');
test.done();
},
};