[Pkg-javascript-commits] [node-grunt-legacy-util] 01/04: Import Upstream version 1.0.0

Sruthi Chandran srud-guest at moszumanska.debian.org
Fri Nov 11 07:18:08 UTC 2016


This is an automated email from the git hooks/post-receive script.

srud-guest pushed a commit to branch master
in repository node-grunt-legacy-util.

commit 81d7564ffb123e36f173379c31a172b0946eea71
Author: Sruthi <srud at disroot.org>
Date:   Fri Nov 11 12:31:21 2016 +0530

    Import Upstream version 1.0.0
---
 .gitignore                                |   1 +
 .jshintrc                                 |  14 +
 .travis.yml                               |  16 +
 CHANGELOG                                 |   5 +
 Gruntfile.js                              |  30 ++
 LICENSE-MIT                               |  22 ++
 README.md                                 |  32 ++
 appveyor.yml                              |  29 ++
 index.js                                  | 201 +++++++++++
 package.json                              |  43 +++
 test/fixtures/Gruntfile-execArgv-child.js |   7 +
 test/fixtures/Gruntfile-execArgv.js       |  17 +
 test/fixtures/Gruntfile-print-text.js     |   8 +
 test/fixtures/exec.cmd                    |   1 +
 test/fixtures/exec.sh                     |   2 +
 test/fixtures/spawn-multibyte.js          |  17 +
 test/fixtures/spawn.js                    |   8 +
 test/index.js                             | 554 ++++++++++++++++++++++++++++++
 18 files changed, 1007 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..2b7e39b
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,14 @@
+{
+  "curly": true,
+  "eqeqeq": true,
+  "immed": true,
+  "latedef": "nofunc",
+  "newcap": true,
+  "noarg": true,
+  "sub": true,
+  "undef": true,
+  "unused": true,
+  "boss": true,
+  "eqnull": true,
+  "node": true
+}
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..c6fdaff
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,16 @@
+sudo: false
+language: node_js
+node_js:
+  - "0.10"
+  - "0.12"
+  - "4.0"
+  - "4.1"
+  - "4.2"
+  - "5"
+  - "iojs"
+before_install:
+  - npm install -g npm
+before_script:
+  - npm install -g grunt-cli
+matrix:
+  fast_finish: true
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
index 0000000..d84083f
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,5 @@
+v1.0.0:
+  date: 2016-04-03
+  changes:
+    - test fixes for Windows
+    - update to use the svg badge
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..d7e5845
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,30 @@
+'use strict';
+
+module.exports = function(grunt) {
+
+  grunt.initConfig({
+    jshint: {
+      options: {
+        jshintrc: '.jshintrc',
+      },
+      all: ['*.js', 'test/*.js'],
+    },
+    nodeunit: {
+      util: ['test/index.js']
+    },
+    watch: {
+      all: {
+        files: ['<%= jshint.all %>'],
+        tasks: ['test'],
+      },
+    },
+  });
+
+  grunt.loadNpmTasks('grunt-contrib-jshint');
+  grunt.loadNpmTasks('grunt-contrib-nodeunit');
+  grunt.loadNpmTasks('grunt-contrib-watch');
+
+  grunt.registerTask('test', ['jshint', 'nodeunit']);
+  grunt.registerTask('default', ['test', 'watch']);
+
+};
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..8ac94f0
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,22 @@
+Copyright (c) 2016 "Cowboy" Ben Alman
+
+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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1cdd1f7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,32 @@
+# grunt-legacy-util
+> deprecated utilities from grunt
+
+[![Build Status: Linux](https://travis-ci.org/gruntjs/grunt-legacy-util.svg?branch=master)](https://travis-ci.org/gruntjs/grunt-legacy-util)
+[![Build status: Windows](https://ci.appveyor.com/api/projects/status/63a5pjh5hy0wgtx0/branch/master?svg=true)](https://ci.appveyor.com/project/gruntjs/grunt-legacy-util/branch/master)
+[![Built with Grunt](https://cdn.gruntjs.com/builtwith.svg)](http://gruntjs.com/)
+
+With the next major release of Grunt, we will no longer support these APIs.  Where possible, please use the recommended modules in their place.  If you would like to support or improve any of these APIs, please notify us when you have published a backwards compatible npm module—we will then recommend its usage here.
+
+`grunt.util.namespace` use [getobject]  
+`grunt.util.hooker` use [hooker]  
+`grunt.util.async` use [async]  
+`grunt.util._` use [lodash]  
+`grunt.util.exit` use [exit]  
+`grunt.util.callbackify`  
+`grunt.util.error`  
+`grunt.util.linefeed`  
+`grunt.util.normalizelf`  
+`grunt.util.kindOf` use [lodash]  
+`grunt.util.toArray`
+`grunt.util.repeat`  
+`grunt.util.pluralize`  
+`grunt.util.recurse` use [traverse]  
+`grunt.util.spawn` use [require('child_process').spawn]  
+
+[getobject]: https://www.npmjs.org/package/getobject
+[hooker]: https://www.npmjs.org/package/hooker
+[async]: https://www.npmjs.org/package/async
+[lodash]: https://www.npmjs.org/package/lodash
+[exit]: https://www.npmjs.org/package/exit
+[traverse]: https://www.npmjs.org/package/traverse
+[require('child_process').spawn]: https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..aeec38a
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,29 @@
+# Fix line endings on Windows
+init:
+  - git config --global core.autocrlf true
+# What combinations to test
+environment:
+  matrix:
+    - nodejs_version: "0.10"
+    - nodejs_version: "0.12"
+    - nodejs_version: "4"
+platform:
+  - x86
+  - x64
+install:
+  - ps: Install-Product node $env:nodejs_version
+  - npm install -g grunt-cli
+  - npm install -g npm
+  - npm install
+test_script:
+  # Output useful info for debugging.
+  - node --version && npm --version
+  # We test multiple Windows shells because of prior stdout buffering issues
+  # filed against Grunt. https://github.com/joyent/node/issues/3584
+  - ps: "npm test # PowerShell" # Pass comment to PS for easier debugging
+  - cmd: npm test
+build: off
+matrix:
+  fast_finish: true
+cache:
+  - node_modules -> package.json                                        # local npm modules
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..a61d9cc
--- /dev/null
+++ b/index.js
@@ -0,0 +1,201 @@
+/*
+ * grunt
+ * http://gruntjs.com/
+ *
+ * Copyright (c) 2016 "Cowboy" Ben Alman
+ * Licensed under the MIT license.
+ * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT
+ */
+
+'use strict';
+
+// Nodejs libs.
+var spawn = require('child_process').spawn;
+var nodeUtil = require('util');
+var path = require('path');
+
+// The module to be exported.
+var util = module.exports = {};
+
+util.namespace = require('getobject');
+
+// External libs.
+util.hooker = require('hooker');
+util.async = require('async');
+var _ = util._ = require('lodash');
+var which = require('which').sync;
+// Instead of process.exit. See https://github.com/cowboy/node-exit
+util.exit = require('exit');
+
+// Mixin Underscore.string methods.
+_.str = require('underscore.string');
+_.mixin(_.str.exports());
+
+// Return a function that normalizes the given function either returning a
+// value or accepting a "done" callback that accepts a single value.
+util.callbackify = function(fn) {
+  return function callbackable() {
+    // Invoke original function, getting its result.
+    var result = fn.apply(this, arguments);
+    // If the same number or less arguments were specified than fn accepts,
+    // assume the "done" callback was already handled.
+    var length = arguments.length;
+    if (length === fn.length) { return; }
+    // Otherwise, if the last argument is a function, assume it is a "done"
+    // callback and call it.
+    var done = arguments[length - 1];
+    if (typeof done === 'function') { done(result); }
+  };
+};
+
+// Create a new Error object, with an origError property that will be dumped
+// if grunt was run with the --debug=9 option.
+util.error = function(err, origError) {
+  if (!nodeUtil.isError(err)) { err = new Error(err); }
+  if (origError) { err.origError = origError; }
+  return err;
+};
+
+// The line feed char for the current system.
+util.linefeed = process.platform === 'win32' ? '\r\n' : '\n';
+
+// Normalize linefeeds in a string.
+util.normalizelf = function(str) {
+  return str.replace(/\r\n|\n/g, util.linefeed);
+};
+
+// What "kind" is a value?
+// I really need to rework https://github.com/cowboy/javascript-getclass
+var kindsOf = {};
+'Number String Boolean Function RegExp Array Date Error'.split(' ').forEach(function(k) {
+  kindsOf['[object ' + k + ']'] = k.toLowerCase();
+});
+util.kindOf = function(value) {
+  // Null or undefined.
+  if (value == null) { return String(value); }
+  // Everything else.
+  return kindsOf[kindsOf.toString.call(value)] || 'object';
+};
+
+// Coerce something to an Array.
+util.toArray = _.toArray;
+
+// Return the string `str` repeated `n` times.
+util.repeat = function(n, str) {
+  return new Array(n + 1).join(str || ' ');
+};
+
+// Given str of "a/b", If n is 1, return "a" otherwise "b".
+util.pluralize = function(n, str, separator) {
+  var parts = str.split(separator || '/');
+  return n === 1 ? (parts[0] || '') : (parts[1] || '');
+};
+
+// Recurse through objects and arrays, executing fn for each non-object.
+util.recurse = function(value, fn, fnContinue) {
+  function recurse(value, fn, fnContinue, state) {
+    var error;
+    if (state.objs.indexOf(value) !== -1) {
+      error = new Error('Circular reference detected (' + state.path + ')');
+      error.path = state.path;
+      throw error;
+    }
+    var obj, key;
+    if (fnContinue && fnContinue(value) === false) {
+      // Skip value if necessary.
+      return value;
+    } else if (util.kindOf(value) === 'array') {
+      // If value is an array, recurse.
+      return value.map(function(item, index) {
+        return recurse(item, fn, fnContinue, {
+          objs: state.objs.concat([value]),
+          path: state.path + '[' + index + ']',
+        });
+      });
+    } else if (util.kindOf(value) === 'object' && !Buffer.isBuffer(value)) {
+      // If value is an object, recurse.
+      obj = {};
+      for (key in value) {
+        obj[key] = recurse(value[key], fn, fnContinue, {
+          objs: state.objs.concat([value]),
+          path: state.path + (/\W/.test(key) ? '["' + key + '"]' : '.' + key),
+        });
+      }
+      return obj;
+    } else {
+      // Otherwise pass value into fn and return.
+      return fn(value);
+    }
+  }
+  return recurse(value, fn, fnContinue, {objs: [], path: ''});
+};
+
+// Spawn a child process, capturing its stdout and stderr.
+util.spawn = function(opts, done) {
+  // Build a result object and pass it (among other things) into the
+  // done function.
+  var callDone = function(code, stdout, stderr) {
+    // Remove trailing whitespace (newline)
+    stdout = _.rtrim(stdout);
+    stderr = _.rtrim(stderr);
+    // Create the result object.
+    var result = {
+      stdout: stdout,
+      stderr: stderr,
+      code: code,
+      toString: function() {
+        if (code === 0) {
+          return stdout;
+        } else if ('fallback' in opts) {
+          return opts.fallback;
+        } else if (opts.grunt) {
+          // grunt.log.error uses standard out, to be fixed in 0.5.
+          return stderr || stdout;
+        }
+        return stderr;
+      }
+    };
+    // On error (and no fallback) pass an error object, otherwise pass null.
+    done(code === 0 || 'fallback' in opts ? null : new Error(stderr), result, code);
+  };
+
+  var cmd, args;
+  var pathSeparatorRe = /[\\\/]/g;
+  if (opts.grunt) {
+    cmd = process.execPath;
+    args = process.execArgv.concat(process.argv[1], opts.args);
+  } else {
+    // On Windows, child_process.spawn will only file .exe files in the PATH,
+    // not other executable types (grunt issue #155).
+    try {
+      if (!pathSeparatorRe.test(opts.cmd)) {
+        // Only use which if cmd has no path component.
+        cmd = which(opts.cmd);
+      } else {
+        cmd = opts.cmd.replace(pathSeparatorRe, path.sep);
+      }
+    } catch (err) {
+      callDone(127, '', String(err));
+      return;
+    }
+    args = opts.args || [];
+  }
+
+  var child = spawn(cmd, args, opts.opts);
+  var stdout = new Buffer('');
+  var stderr = new Buffer('');
+  if (child.stdout) {
+    child.stdout.on('data', function(buf) {
+      stdout = Buffer.concat([stdout, new Buffer(buf)]);
+    });
+  }
+  if (child.stderr) {
+    child.stderr.on('data', function(buf) {
+      stderr = Buffer.concat([stderr, new Buffer(buf)]);
+    });
+  }
+  child.on('close', function(code) {
+    callDone(code, stdout.toString(), stderr.toString());
+  });
+  return child;
+};
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..7e6d7e6
--- /dev/null
+++ b/package.json
@@ -0,0 +1,43 @@
+{
+  "name": "grunt-legacy-util",
+  "description": "Some old grunt utils provided for backwards compatibility.",
+  "version": "1.0.0",
+  "author": "\"Cowboy\" Ben Alman (http://benalman.com/)",
+  "homepage": "http://gruntjs.com/",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/gruntjs/grunt-legacy-util.git"
+  },
+  "bugs": {
+    "url": "http://github.com/gruntjs/grunt-legacy-util/issues"
+  },
+  "license": "MIT",
+  "main": "index.js",
+  "scripts": {
+    "test": "grunt test"
+  },
+  "engines": {
+    "node": ">= 0.10.0"
+  },
+  "keywords": [
+    "grunt",
+    "legacy"
+  ],
+  "dependencies": {
+    "async": "~1.5.2",
+    "exit": "~0.1.1",
+    "getobject": "~0.1.0",
+    "hooker": "~0.2.3",
+    "lodash": "~4.3.0",
+    "underscore.string": "~3.2.3",
+    "which": "~1.2.1"
+  },
+  "devDependencies": {
+    "grunt": "^0.4.5",
+    "grunt-cli": "^1.2.0",
+    "grunt-contrib-jshint": "^1.0.0",
+    "grunt-contrib-nodeunit": "^1.0.0",
+    "grunt-contrib-watch": "^1.0.0",
+    "temporary": "0.0.8"
+  }
+}
diff --git a/test/fixtures/Gruntfile-execArgv-child.js b/test/fixtures/Gruntfile-execArgv-child.js
new file mode 100644
index 0000000..f0d1d1f
--- /dev/null
+++ b/test/fixtures/Gruntfile-execArgv-child.js
@@ -0,0 +1,7 @@
+module.exports = function(grunt) {
+
+  grunt.registerTask('default', function(text) {
+    console.log('OUTPUT: ' + process.execArgv.join(' '));
+  });
+
+};
diff --git a/test/fixtures/Gruntfile-execArgv.js b/test/fixtures/Gruntfile-execArgv.js
new file mode 100644
index 0000000..7ad3db0
--- /dev/null
+++ b/test/fixtures/Gruntfile-execArgv.js
@@ -0,0 +1,17 @@
+module.exports = function(grunt) {
+
+  var util = require('../../');
+
+  grunt.registerTask('default', function(text) {
+    var done = this.async();
+    util.spawn({
+      grunt: true,
+      args: ['--gruntfile', 'Gruntfile-execArgv-child.js'],
+    }, function(err, result, code) {
+      var matches = result.stdout.match(/^(OUTPUT: .*)/m);
+      console.log(matches ? matches[1] : '');
+      done();
+    });
+  });
+
+};
diff --git a/test/fixtures/Gruntfile-print-text.js b/test/fixtures/Gruntfile-print-text.js
new file mode 100644
index 0000000..910197d
--- /dev/null
+++ b/test/fixtures/Gruntfile-print-text.js
@@ -0,0 +1,8 @@
+module.exports = function(grunt) {
+
+  grunt.registerTask('print', 'Print the specified text.', function(text) {
+    console.log('OUTPUT: ' + text);
+    // console.log(process.cwd());
+  });
+
+};
diff --git a/test/fixtures/exec.cmd b/test/fixtures/exec.cmd
new file mode 100644
index 0000000..6e4a52b
--- /dev/null
+++ b/test/fixtures/exec.cmd
@@ -0,0 +1 @@
+ at echo done
diff --git a/test/fixtures/exec.sh b/test/fixtures/exec.sh
new file mode 100755
index 0000000..8890799
--- /dev/null
+++ b/test/fixtures/exec.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+echo "done"
diff --git a/test/fixtures/spawn-multibyte.js b/test/fixtures/spawn-multibyte.js
new file mode 100644
index 0000000..8277711
--- /dev/null
+++ b/test/fixtures/spawn-multibyte.js
@@ -0,0 +1,17 @@
+// This is a test fixture for a case where spawn receives incomplete
+// multibyte strings in separate data events.
+
+// A multibyte buffer containing all our output. We will slice it later.
+// In this case we are using a Japanese word for hello / good day, where each
+// character takes three bytes.
+var fullOutput = new Buffer('こんにちは');
+
+// Output one full character and one third of a character
+process.stdout.write(fullOutput.slice(0, 4));
+
+// Output the rest of the string
+process.stdout.write(fullOutput.slice(4));
+
+// Do the same for stderr
+process.stderr.write(fullOutput.slice(0, 4));
+process.stderr.write(fullOutput.slice(4));
diff --git a/test/fixtures/spawn.js b/test/fixtures/spawn.js
new file mode 100644
index 0000000..14c7029
--- /dev/null
+++ b/test/fixtures/spawn.js
@@ -0,0 +1,8 @@
+
+var code = Number(process.argv[2]);
+
+process.stdout.write('stdout\n');
+process.stderr.write('stderr\n');
+
+// Instead of process.exit. See https://github.com/cowboy/node-exit
+require('exit')(code);
diff --git a/test/index.js b/test/index.js
new file mode 100644
index 0000000..4a657be
--- /dev/null
+++ b/test/index.js
@@ -0,0 +1,554 @@
+'use strict';
+
+var util = require('../');
+
+var fs = require('fs');
+var path = require('path');
+
+var Tempfile = require('temporary/lib/file');
+
+exports['util.callbackify'] = {
+  'return': function(test) {
+    test.expect(1);
+    // This function returns a value.
+    function add(a, b) {
+      return a + b;
+    }
+    util.callbackify(add)(1, 2, function(result) {
+      test.equal(result, 3, 'should be the correct result.');
+      test.done();
+    });
+  },
+  'callback (sync)': function(test) {
+    test.expect(1);
+    // This function accepts a callback which it calls synchronously.
+    function add(a, b, done) {
+      done(a + b);
+    }
+    util.callbackify(add)(1, 2, function(result) {
+      test.equal(result, 3, 'should be the correct result.');
+      test.done();
+    });
+  },
+  'callback (async)': function(test) {
+    test.expect(1);
+    // This function accepts a callback which it calls asynchronously.
+    function add(a, b, done) {
+      setTimeout(done.bind(null, a + b), 0);
+    }
+    util.callbackify(add)(1, 2, function(result) {
+      test.equal(result, 3, 'should be the correct result.');
+      test.done();
+    });
+  }
+};
+
+exports['util'] = {
+  'error': function(test) {
+    test.expect(9);
+    var origError = new Error('Original error.');
+
+    var err = util.error('Test message.');
+    test.ok(err instanceof Error, 'Should be an Error.');
+    test.equal(err.name, 'Error', 'Should be an Error.');
+    test.equal(err.message, 'Test message.', 'Should have the correct message.');
+
+    err = util.error('Test message.', origError);
+    test.ok(err instanceof Error, 'Should be an Error.');
+    test.equal(err.name, 'Error', 'Should be an Error.');
+    test.equal(err.message, 'Test message.', 'Should have the correct message.');
+    test.equal(err.origError, origError, 'Should reflect the original error.');
+
+    var newError = new Error('Test message.');
+    err = util.error(newError, origError);
+    test.equal(err, newError, 'Should be the passed-in Error.');
+    test.equal(err.origError, origError, 'Should reflect the original error.');
+    test.done();
+  },
+  'linefeed': function(test) {
+    test.expect(1);
+    if (process.platform === 'win32') {
+      test.equal(util.linefeed, '\r\n', 'linefeed should be operating-system appropriate.');
+    } else {
+      test.equal(util.linefeed, '\n', 'linefeed should be operating-system appropriate.');
+    }
+    test.done();
+  },
+  'normalizelf': function(test) {
+    test.expect(1);
+    if (process.platform === 'win32') {
+      test.equal(util.normalizelf('foo\nbar\r\nbaz\r\n\r\nqux\n\nquux'), 'foo\r\nbar\r\nbaz\r\n\r\nqux\r\n\r\nquux', 'linefeeds should be normalized');
+    } else {
+      test.equal(util.normalizelf('foo\nbar\r\nbaz\r\n\r\nqux\n\nquux'), 'foo\nbar\nbaz\n\nqux\n\nquux', 'linefeeds should be normalized');
+    }
+    test.done();
+  }
+};
+
+exports['util.spawn'] = {
+  setUp: function(done) {
+    this.script = path.resolve('test/fixtures/spawn.js');
+    done();
+  },
+  'exit code 0': function(test) {
+    test.expect(6);
+    util.spawn({
+      cmd: process.execPath,
+      args: [ this.script, 0 ],
+    }, function(err, result, code) {
+      test.equals(err, null);
+      test.equals(code, 0);
+      test.equals(result.stdout, 'stdout');
+      test.equals(result.stderr, 'stderr');
+      test.equals(result.code, 0);
+      test.equals(String(result), 'stdout');
+      test.done();
+    });
+  },
+  'exit code 0, fallback': function(test) {
+    test.expect(6);
+    util.spawn({
+      cmd: process.execPath,
+      args: [ this.script, 0 ],
+      fallback: 'ignored if exit code is 0'
+    }, function(err, result, code) {
+      test.equals(err, null);
+      test.equals(code, 0);
+      test.equals(result.stdout, 'stdout');
+      test.equals(result.stderr, 'stderr');
+      test.equals(result.code, 0);
+      test.equals(String(result), 'stdout');
+      test.done();
+    });
+  },
+  'non-zero exit code': function(test) {
+    test.expect(7);
+    util.spawn({
+      cmd: process.execPath,
+      args: [ this.script, 123 ],
+    }, function(err, result, code) {
+      test.ok(err instanceof Error);
+      test.equals(err.message, 'stderr');
+      test.equals(code, 123);
+      test.equals(result.stdout, 'stdout');
+      test.equals(result.stderr, 'stderr');
+      test.equals(result.code, 123);
+      test.equals(String(result), 'stderr');
+      test.done();
+    });
+  },
+  'non-zero exit code, fallback': function(test) {
+    test.expect(6);
+    util.spawn({
+      cmd: process.execPath,
+      args: [ this.script, 123 ],
+      fallback: 'custom fallback'
+    }, function(err, result, code) {
+      test.equals(err, null);
+      test.equals(code, 123);
+      test.equals(result.stdout, 'stdout');
+      test.equals(result.stderr, 'stderr');
+      test.equals(result.code, 123);
+      test.equals(String(result), 'custom fallback');
+      test.done();
+    });
+  },
+  'cmd not found': function(test) {
+    test.expect(3);
+    util.spawn({
+      cmd: 'nodewtfmisspelled',
+    }, function(err, result, code) {
+      test.ok(err instanceof Error);
+      test.equals(code, 127);
+      test.equals(result.code, 127);
+      test.done();
+    });
+  },
+  'cmd not found, fallback': function(test) {
+    test.expect(4);
+    util.spawn({
+      cmd: 'nodewtfmisspelled',
+      fallback: 'use a fallback or good luck'
+    }, function(err, result, code) {
+      test.equals(err, null);
+      test.equals(code, 127);
+      test.equals(result.code, 127);
+      test.equals(String(result), 'use a fallback or good luck');
+      test.done();
+    });
+  },
+  'cmd not in path': function(test) {
+    test.expect(6);
+    var win32 = process.platform === 'win32';
+    util.spawn({
+      cmd: 'test\\fixtures\\exec' + (win32 ? '.cmd' : '.sh'),
+    }, function(err, result, code) {
+      test.equals(err, null);
+      test.equals(code, 0);
+      test.equals(result.stdout, 'done');
+      test.equals(result.stderr, '');
+      test.equals(result.code, 0);
+      test.equals(String(result), 'done');
+      test.done();
+    });
+  },
+  'cmd not in path (with cwd)': function(test) {
+    test.expect(6);
+    var win32 = process.platform === 'win32';
+    util.spawn({
+      cmd: './exec' + (win32 ? '.cmd' : '.sh'),
+      opts: {cwd: 'test/fixtures'},
+    }, function(err, result, code) {
+      test.equals(err, null);
+      test.equals(code, 0);
+      test.equals(result.stdout, 'done');
+      test.equals(result.stderr, '');
+      test.equals(result.code, 0);
+      test.equals(String(result), 'done');
+      test.done();
+    });
+  },
+  'grunt': function(test) {
+    test.expect(3);
+    util.spawn({
+      grunt: true,
+      args: [ '--gruntfile', 'test/fixtures/Gruntfile-print-text.js', 'print:foo' ],
+    }, function(err, result, code) {
+      test.equals(err, null);
+      test.equals(code, 0);
+      test.ok(/^OUTPUT: foo/m.test(result.stdout), 'stdout should contain output indicating the grunt task was run.');
+      test.done();
+    });
+  },
+  'grunt (with cwd)': function(test) {
+    test.expect(3);
+    util.spawn({
+      grunt: true,
+      args: [ '--gruntfile', 'Gruntfile-print-text.js', 'print:foo' ],
+      opts: {cwd: 'test/fixtures'},
+    }, function(err, result, code) {
+      test.equals(err, null);
+      test.equals(code, 0);
+      test.ok(/^OUTPUT: foo/m.test(result.stdout), 'stdout should contain output indicating the grunt task was run.');
+      test.done();
+    });
+  },
+  'grunt passes execArgv': function(test) {
+    test.expect(3);
+    util.spawn({
+      cmd: process.execPath,
+      args: [ '--harmony', process.argv[1], '--gruntfile', 'test/fixtures/Gruntfile-execArgv.js'],
+    }, function(err, result, code) {
+      test.equals(err, null);
+      test.equals(code, 0);
+      test.ok(/^OUTPUT: --harmony/m.test(result.stdout), 'stdout should contain passed-through process.execArgv.');
+      test.done();
+    });
+  },
+  'grunt result.toString() with error': function(test) {
+    // grunt.log.error uses standard out, to be fixed in 0.5.
+    test.expect(4);
+    util.spawn({
+      grunt: true,
+      args: [ 'nonexistentTask' ]
+    }, function(err, result, code) {
+      test.ok(err instanceof Error, 'Should be an Error.');
+      test.equal(err.name, 'Error', 'Should be an Error.');
+      test.equals(code, 3);
+      test.ok(/Warning: Task "nonexistentTask" not found./m.test(result.toString()), 'stdout should contain output indicating the grunt task was (attempted to be) run.');
+      test.done();
+    });
+  },
+  'custom stdio stream(s)': function(test) {
+    test.expect(6);
+    var stdoutFile = new Tempfile();
+    var stderrFile = new Tempfile();
+    var stdout = fs.openSync(stdoutFile.path, 'a');
+    var stderr = fs.openSync(stderrFile.path, 'a');
+    var child = util.spawn({
+      cmd: process.execPath,
+      args: [ this.script, 0 ],
+      opts: {stdio: [null, stdout, stderr]},
+    }, function(err, result, code) {
+      test.equals(code, 0);
+      test.equals(String(fs.readFileSync(stdoutFile.path)), 'stdout\n', 'Child process stdout should have been captured via custom stream.');
+      test.equals(String(fs.readFileSync(stderrFile.path)), 'stderr\n', 'Child process stderr should have been captured via custom stream.');
+      stdoutFile.unlinkSync();
+      stderrFile.unlinkSync();
+      test.equals(result.stdout, '', 'Nothing will be passed to the stdout string when spawn stdio is a custom stream.');
+      test.done();
+    });
+    test.ok(!child.stdout, 'child should not have a stdout property.');
+    test.ok(!child.stderr, 'child should not have a stderr property.');
+  },
+};
+
+exports['util.spawn.multibyte'] = {
+  setUp: function(done) {
+    this.script = path.resolve('test/fixtures/spawn-multibyte.js');
+    done();
+  },
+  'partial stdout': function(test) {
+    test.expect(4);
+    util.spawn({
+      cmd: process.execPath,
+      args: [ this.script ],
+    }, function(err, result, code) {
+      test.equals(err, null);
+      test.equals(code, 0);
+      test.equals(result.stdout, 'こんにちは');
+      test.equals(result.stderr, 'こんにちは');
+      test.done();
+    });
+  }
+};
+
+exports['util.underscore.string'] = function(test) {
+  test.expect(4);
+  test.equals(util._.trim('    foo     '), 'foo', 'Should have trimmed the string.');
+  test.equals(util._.capitalize('foo'), 'Foo', 'Should have capitalized the first letter.');
+  test.equals(util._.words('one two three').length, 3, 'Should have counted three words.');
+  test.ok(util._.isBlank(' '), 'Should be blank.');
+  test.done();
+};
+
+function getType(val) {
+  if (Buffer.isBuffer(val)) { return 'buffer'; }
+  return Object.prototype.toString.call(val).slice(8, -1).toLowerCase();
+}
+
+exports['util.recurse'] = {
+  setUp: function(done) {
+    this.typeValue = function(value) {
+      return {
+        value: value,
+        type: getType(value),
+      };
+    };
+    done();
+  },
+  'primitives': function(test) {
+    test.expect(1);
+    var actual = util.recurse({
+      bool: true,
+      num: 1,
+      str: 'foo',
+      nul: null,
+      undef: undefined,
+    }, this.typeValue);
+    var expected = {
+      bool: {type: 'boolean', value: true},
+      num: {type: 'number', value: 1},
+      str: {type: 'string', value: 'foo'},
+      nul: {type: 'null', value: null},
+      undef: {type: 'undefined', value: undefined},
+    };
+    test.deepEqual(actual, expected, 'Should process primitive values.');
+    test.done();
+  },
+  'array': function(test) {
+    test.expect(1);
+    var actual = util.recurse({
+      arr: [
+        true,
+        1,
+        'foo',
+        null,
+        undefined,
+        [
+          true,
+          1,
+          'foo',
+          null,
+          undefined,
+        ],
+      ],
+    }, this.typeValue);
+    var expected = {
+      arr: [
+        {type: 'boolean', value: true},
+        {type: 'number', value: 1},
+        {type: 'string', value: 'foo'},
+        {type: 'null', value: null},
+        {type: 'undefined', value: undefined},
+        [
+          {type: 'boolean', value: true},
+          {type: 'number', value: 1},
+          {type: 'string', value: 'foo'},
+          {type: 'null', value: null},
+          {type: 'undefined', value: undefined},
+        ],
+      ],
+    };
+    test.deepEqual(actual, expected, 'Should recurse over arrays.');
+    test.done();
+  },
+  'object': function(test) {
+    test.expect(1);
+    var actual = util.recurse({
+      obj: {
+        bool: true,
+        num: 1,
+        str: 'foo',
+        nul: null,
+        undef: undefined,
+        obj: {
+          bool: true,
+          num: 1,
+          str: 'foo',
+          nul: null,
+          undef: undefined,
+        },
+      },
+    }, this.typeValue);
+    var expected = {
+      obj: {
+        bool: {type: 'boolean', value: true},
+        num: {type: 'number', value: 1},
+        str: {type: 'string', value: 'foo'},
+        nul: {type: 'null', value: null},
+        undef: {type: 'undefined', value: undefined},
+        obj: {
+          bool: {type: 'boolean', value: true},
+          num: {type: 'number', value: 1},
+          str: {type: 'string', value: 'foo'},
+          nul: {type: 'null', value: null},
+          undef: {type: 'undefined', value: undefined},
+        },
+      },
+    };
+    test.deepEqual(actual, expected, 'Should recurse over objects.');
+    test.done();
+  },
+  'array in object': function(test) {
+    test.expect(1);
+    var actual = util.recurse({
+      obj: {
+        arr: [
+          true,
+          1,
+          'foo',
+          null,
+          undefined,
+        ],
+      },
+    }, this.typeValue);
+    var expected = {
+      obj: {
+        arr: [
+          {type: 'boolean', value: true},
+          {type: 'number', value: 1},
+          {type: 'string', value: 'foo'},
+          {type: 'null', value: null},
+          {type: 'undefined', value: undefined},
+        ],
+      },
+    };
+    test.deepEqual(actual, expected, 'Should recurse over arrays in objects.');
+    test.done();
+  },
+  'object in array': function(test) {
+    test.expect(1);
+    var actual = util.recurse({
+      arr: [
+        true,
+        {
+          num: 1,
+          str: 'foo',
+        },
+        null,
+        undefined,
+      ],
+    }, this.typeValue);
+    var expected = {
+      arr: [
+        {type: 'boolean', value: true},
+        {
+          num: {type: 'number', value: 1},
+          str: {type: 'string', value: 'foo'},
+        },
+        {type: 'null', value: null},
+        {type: 'undefined', value: undefined},
+      ],
+    };
+    test.deepEqual(actual, expected, 'Should recurse over objects in arrays.');
+    test.done();
+  },
+  'buffer': function(test) {
+    test.expect(1);
+    var actual = util.recurse({
+      buf: new Buffer('buf'),
+    }, this.typeValue);
+    var expected = {
+      buf: {type: 'buffer', value: new Buffer('buf')},
+    };
+    test.deepEqual(actual, expected, 'Should not mangle Buffer instances.');
+    test.done();
+  },
+  'inherited properties': function(test) {
+    test.expect(1);
+    var actual = util.recurse({
+      obj: Object.create({num: 1}, {
+        str: {value: 'foo', enumerable: true},
+        ignored: {value: 'ignored', enumerable: false},
+      }),
+    }, this.typeValue);
+    var expected = {
+      obj: {
+        num: {type: 'number', value: 1},
+        str: {type: 'string', value: 'foo'},
+      }
+    };
+    test.deepEqual(actual, expected, 'Should enumerate inherited object properties.');
+    test.done();
+  },
+  'circular references': function(test) {
+    test.expect(6);
+    function assertErrorWithPath(expectedPath) {
+      return function(actual) {
+        return actual.path === expectedPath &&
+          actual.message === 'Circular reference detected (' + expectedPath + ')';
+      };
+    }
+    test.doesNotThrow(function() {
+      var obj = {
+        // wat
+        a:[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
+        // does
+        b:[[[[],[[[],[[[[],[[[],[[[],[[[],[[[],[[[[],[[]]]]]]]]]]]]]]]]]]]]],
+        // it
+        c:{d:{e:{f:{g:{h:{i:{j:{k:{l:{m:{n:{o:{p:{q:{r:{s:{}}}}}}}}}}}}}}}}},
+        // mean
+        t:[{u:[{v:[[[[],[[[],[[[{w:[{x:[[[],[[[{y:[[1]]}]]]]]}]}]]]]]]]]}]}],
+      };
+      util.recurse(obj, function(v) { return v; });
+    }, 'Should not throw when no circular reference is detected.');
+    test.throws(function() {
+      var obj = {a: 1, b: 2};
+      obj.obj = obj;
+      util.recurse(obj, function(v) { return v; });
+    }, assertErrorWithPath('.obj'), 'Should throw when a circular reference is detected.');
+    test.throws(function() {
+      var obj = {a:{'b b':{'c-c':{d_d:{e:{f:{g:{h:{i:{j:{k:{l:{}}}}}}}}}}}}};
+      obj.a['b b']['c-c'].d_d.e.f.g.h.i.j.k.l.obj = obj;
+      util.recurse(obj, function(v) { return v; });
+    }, assertErrorWithPath('.a["b b"]["c-c"].d_d.e.f.g.h.i.j.k.l.obj'), 'Should throw when a circular reference is detected.');
+    test.throws(function() {
+      var obj = {a: 1, b: 2};
+      obj.arr = [1, 2, obj, 3, 4];
+      util.recurse(obj, function(v) { return v; });
+    }, assertErrorWithPath('.arr[2]'), 'Should throw when a circular reference is detected.');
+    test.throws(function() {
+      var obj = {a: 1, b: 2};
+      obj.arr = [{a:[1,{b:[2,{c:[3,obj,4]},5]},6]},7];
+      util.recurse(obj, function(v) { return v; });
+    }, assertErrorWithPath('.arr[0].a[1].b[1].c[1]'), 'Should throw when a circular reference is detected.');
+    test.throws(function() {
+      var obj = {a: 1, b: 2};
+      obj.arr = [];
+      obj.arr.push(0,{a:[1,{b:[2,{c:[3,obj.arr,4]},5]},6]},7);
+      util.recurse(obj, function(v) { return v; });
+    }, assertErrorWithPath('.arr[1].a[1].b[1].c[1]'), 'Should throw when a circular reference is detected.');
+    test.done();
+  },
+};

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-grunt-legacy-util.git



More information about the Pkg-javascript-commits mailing list