git-off

git off handles large files in git repos
git clone https://noulin.net/git/git-off.git
Log | Files | Refs | README

commit a4cb60563a5af388c2a2eb44dfb2b54969fc32a0
Author: Remy Noulin (Spartatek) <remy.noulin@spartatek.se>
Date:   Sun, 20 Nov 2016 10:55:10 +0100

first working prototype - copy - add/push/checkout working

Diffstat:
A.gitignore | 1+
Abin/git-off | 2++
Asrc/gitoff.coffee | 268+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/colors/LICENSE | 24++++++++++++++++++++++++
Asrc/node_modules/colors/ReadMe.md | 178+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/colors/examples/normal-usage.js | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/colors/examples/safe-string.js | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/colors/lib/colors.js | 188+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/colors/lib/custom/trap.js | 45+++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/colors/lib/custom/zalgo.js | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/colors/lib/extendStringPrototype.js | 114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/colors/lib/index.js | 13+++++++++++++
Asrc/node_modules/colors/lib/maps/america.js | 13+++++++++++++
Asrc/node_modules/colors/lib/maps/rainbow.js | 13+++++++++++++
Asrc/node_modules/colors/lib/maps/random.js | 9+++++++++
Asrc/node_modules/colors/lib/maps/zebra.js | 6++++++
Asrc/node_modules/colors/lib/styles.js | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/colors/lib/system/supports-colors.js | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/colors/package.json | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/colors/safe.js | 10++++++++++
Asrc/node_modules/colors/themes/generic-logging.js | 13+++++++++++++
Asrc/node_modules/sync-exec/.npmignore | 4++++
Asrc/node_modules/sync-exec/LICENSE | 21+++++++++++++++++++++
Asrc/node_modules/sync-exec/Makefile | 13+++++++++++++
Asrc/node_modules/sync-exec/README.md | 40++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/sync-exec/coffee/lib/create-pipes.coffee | 28++++++++++++++++++++++++++++
Asrc/node_modules/sync-exec/coffee/lib/proxy.coffee | 32++++++++++++++++++++++++++++++++
Asrc/node_modules/sync-exec/coffee/lib/read-pipes.coffee | 40++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/sync-exec/coffee/lib/timeout.coffee | 7+++++++
Asrc/node_modules/sync-exec/coffee/sync-exec.coffee | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/sync-exec/js/lib/create-pipes.js | 31+++++++++++++++++++++++++++++++
Asrc/node_modules/sync-exec/js/lib/proxy.js | 33+++++++++++++++++++++++++++++++++
Asrc/node_modules/sync-exec/js/lib/read-pipes.js | 44++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/sync-exec/js/lib/timeout.js | 9+++++++++
Asrc/node_modules/sync-exec/js/sync-exec.js | 48++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/sync-exec/package.json | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/sync-exec/test/example.coffee | 44++++++++++++++++++++++++++++++++++++++++++++
Asrc/node_modules/sync-exec/test/sh/err.sh | 4++++
Asrc/node_modules/sync-exec/test/sh/out.sh | 2++
39 files changed, 1857 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1 @@ +*.sw* diff --git a/bin/git-off b/bin/git-off @@ -0,0 +1 @@ +../src/gitoff.coffee+ \ No newline at end of file diff --git a/src/gitoff.coffee b/src/gitoff.coffee @@ -0,0 +1,268 @@ +#! /usr/bin/env coffee + +# TODO +# problem with clean - file in subdir missing +# smudge doesnt work +# detect when not setup +# parse params +# log +# debug log +# read only files in store +# default setup global +# option to setup locally +# +# config: +# gitoff mode rsync, http, copy, move +# store=/we + +require('colors') +fs = require('fs') +syncexec = require('sync-exec') + +exec = (cmd) -> + #console.log cmd + r = syncexec cmd + #console.log r + #console.log r.stdout + if r.stderr != '' + console.log r.stderr.red.bold + process.exit(1) + r + +# objInfo fields +oiPREVIOUSPERMISSIONS = 0 +oiPERMISSIONS = 1 +oiPREVIOUSOID = 2 +oiOID = 3 +oiNAME = 4 + +# example: exec externalHelpers.gitRepoRoot +externalHelpers = + 'gitConfigGlobal': 'git config --global' + 'gitConfig': 'git config' + 'gitRepoRoot': 'git rev-parse --show-toplevel' + 'gitList': 'git rev-list' + 'gitDiff': 'git diff-tree -r' + 'gitCat': 'git cat-file -p' + #'sha': 'sha256sum' + 'sha': 'git hash-object --no-filters' + 'fileSize': 'du -b' + 'mkdir': 'mkdir' + 'mkdirParent': 'mkdir -p' + 'copy': 'cp' + 'rmAll': 'rm -rf' + 'chmod': 'chmod' + 'move': 'mv' + 'cat': 'cat' + +# use offHelpers to access runtimeConfig +runtimeConfig = + 'currentRepoRoot': '' + 'objectPath': '' + 'offStore': '' + +offDEFAULTS = + 'objectPath': '/.git/off/objects' + 'mode': 'move' + 'store': '~/.git-off/offStore' + 'prePush': '#!/bin/sh\ncommand -v git-off >/dev/null 2>&1 || { echo >&2 "\\nThis repository is configured for Git off but \'git-off\' was not found on your path. If you no longer wish to use git off, remove this hook by deleting .git/hooks/pre-push.\\n"; exit 2; }\ngit off pre-push "$@"' + 'offSignature': '### git-off v1 sha:' + 'shaLength': 40 + +offHelpers = + 'gitRepoRoot': -> + if runtimeConfig.currentRepoRoot == '' + r = exec externalHelpers.gitRepoRoot + runtimeConfig.currentRepoRoot = r.stdout.trim() + runtimeConfig.currentRepoRoot + 'objectPath': -> + if runtimeConfig.objectPath == '' + runtimeConfig.objectPath = this.gitRepoRoot() + offDEFAULTS.objectPath + runtimeConfig.objectPath + 'offStore': -> + if runtimeConfig.offStore == '' + r = exec externalHelpers.gitConfig + ' off.store' + runtimeConfig.offStore = r.stdout.trim().replace('~/', process.env.HOME + '/') + runtimeConfig.offStore + 'push': (line) -> + len = process.argv.length + + remoteName = process.argv[len-2] + url = process.argv[len-1] + + line_l = line.split(' ') + + localRef = line_l[0] + localSha = line_l[1] + remoteRef = line_l[2] + remoteSha = line_l[3] + + #console.log remoteName + #console.log url + #console.log localRef + #console.log localSha + #console.log remoteRef + #console.log remoteSha + + r = exec externalHelpers.gitList + ' ' + localSha + ' ^' + remoteSha + commitListToPush = r.stdout.split('\n') + # remove last empty line + commitListToPush = commitListToPush.slice(0, commitListToPush.length-1) + + #console.log '---' + for sha in commitListToPush + r = exec externalHelpers.gitDiff + ' ' + sha + # :000000 100644 0000000000000000000000000000000000000000 23636079ef005f53e81066aaf092521d8f2346df A dsd + objInfoList = r.stdout.split('\n') + # remove first line (commit) and last empty line + objInfoList = objInfoList.slice(1, objInfoList.length-1) + for oi in objInfoList + objInfo = oi.split(' ') + if objInfo[oiNAME].slice(0,1) != 'D' + # dont consider deleted files + r = exec externalHelpers.gitCat + ' ' + objInfo[oiOID] + offRef = r.stdout.split('\n')[0] + #console.log 'cat' + #console.log offRef + + if offRef.indexOf(offDEFAULTS.offSignature) != -1 + # found an off reference + # ### git-off v1 sha:be3e02b60effe3eab232d5590a6a2e2c2c2f443b size:119 b.bin + offFile = offRef.split(':')[1].split(' ')[0] + exec externalHelpers.copy + ' ' + offHelpers.objectPath() + '/' + offFile + ' ' + offHelpers.offStore() + '/' + offFile + #console.log '---' + # test prevent push + #process.exit(1) + return + 'smudge': (line, file) -> + if line.indexOf(offDEFAULTS.offSignature) != -1 + fs.appendFileSync(offHelpers.gitRepoRoot() + '/.git/off/log', line + '\n') + # found an off reference + offFile = line.split(':')[1].split(' ')[0] + # TODO stream cat to stdout + readStream = fs.createReadStream(offHelpers.offStore() + '/' + offFile) + readStream.pipe(process.stdout) + #r = exec externalHelpers.cat + ' ' + offHelpers.offStore() + '/' + offFile + #console.log r.stdout + process.exit(0) + else + console.log line + return + + +globalConfig = + 'set': (key, value)-> + exec externalHelpers.gitConfigGlobal + ' ' + key + ' "' + value + '"' + return + +offCommands = + 'localSetup': -> + exec externalHelpers.mkdirParent + ' ' + offHelpers.objectPath() + fs.writeFileSync(offHelpers.gitRepoRoot() + '/.git/hooks/pre-push', offDEFAULTS.prePush) + exec externalHelpers.chmod + ' ' + '755 ' + offHelpers.gitRepoRoot() + '/.git/hooks/pre-push' + return + 'install': -> + this.localSetup() + globalConfig.set('filter.off.clean','git off clean %f') + globalConfig.set('filter.off.smudge','git off smudge %f') + globalConfig.set('off.mode', offDEFAULTS.mode) + globalConfig.set('off.store',offDEFAULTS.store) + exec externalHelpers.mkdirParent + ' ' + offDEFAULTS.store + return + +if process.argv[2] == 'install' + offCommands.install() + + +if process.argv[2] == 'track' + if process.argv[3] != undefined + offCommands.install() + #TODO git command to add stuff in attributes + fs.writeFileSync(offHelpers.gitRepoRoot() + '/.gitattributes', process.argv[3] + ' filter=off -text') + +if process.argv[2] == 'clean' + offCommands.localSetup() + file = process.argv[3] + r = exec externalHelpers.fileSize + ' ' + file + size = r.stdout.split(' ')[0] + r = exec externalHelpers.sha + ' ' + file + # trim because git hash-object adds \n + offFile = r.stdout.split(' ')[0].trim() + + writeStream = fs.createWriteStream(offHelpers.objectPath() + '/' + offFile) + process.stdin.pipe(writeStream) + #TODO delete doesnt work for binary files - exec externalHelpers.copy + ' ' + file + ' ' + offHelpers.objectPath() + '/' + offFile + console.log offDEFAULTS.offSignature + offFile + ' size:' + size + +if process.argv[2] == 'pre-push' + readline = require('readline') + rl = readline.createInterface( + input: process.stdin + output: process.stdout + terminal: false) + rl.on 'line', (line) -> + offHelpers.push(line) + return + +if process.argv[2] == 'smudge' + offCommands.localSetup() + file = process.argv[3] + fs.appendFileSync(offHelpers.gitRepoRoot() + '/.git/off/log', 'file: ' + file + '\n') + + status = 'header' + process.stdin.on('readable', -> + if status == 'header' + # change status before streaming to stdout + status = 'stream' + + data = process.stdin.read(offDEFAULTS.offSignature.length + offDEFAULTS.shaLength) + StringDecoder = require('string_decoder').StringDecoder + decoder = new StringDecoder('utf8') + fs.appendFileSync(offHelpers.gitRepoRoot() + '/.git/off/log', 'data: ' + data + '\n') + if data == null + process.exit(0) + header = decoder.write(data) + #header = '### git-off v1 sha:502cc54e647403be2487d57bed2e9e2f899691f5' + fs.appendFileSync(offHelpers.gitRepoRoot() + '/.git/off/log', 'header: ' + header + '\n') + fs.appendFileSync(offHelpers.gitRepoRoot() + '/.git/off/log', 'header: ' + header.slice(0,offDEFAULTS.offSignature.length) + '\n') + fs.appendFileSync(offHelpers.gitRepoRoot() + '/.git/off/log', 'signat: ' + offDEFAULTS.offSignature + '\n') + + + if header.slice(0,offDEFAULTS.offSignature.length) == offDEFAULTS.offSignature + offFile = header.split(':')[1] + readStream = fs.createReadStream(offHelpers.offStore() + '/' + offFile) + readStream.pipe(process.stdout) + else + process.stdout.write(data) + process.stdin.pipe(process.stdout) + return) + + # data = process.stdin.read(offDEFAULTS.offSignature.length) + # fs.appendFileSync(offHelpers.gitRepoRoot() + '/.git/off/log', offDEFAULTS.offSignature.length + '\n') + # fs.appendFileSync(offHelpers.gitRepoRoot() + '/.git/off/log', data + '\n') + # if data == offDEFAULTS.offSignature + # offFile = process.stdin.read(offDEFAULTS.shaLength) + # readStream = fs.createReadStream(offHelpers.offStore() + '/' + offFile) + # readStream.pipe(process.stdout) + # else + # if data != null + # process.stdout.write(data) + # process.stdin.pipe(process.stdout) + + + # readline = require('readline') + # rl = readline.createInterface( + # input: process.stdin + # output: process.stdout + # terminal: false) + # rl.on 'line', (line) -> + # offHelpers.smudge(line, file) + # return + +if (process.argv[2] == 'clearAll') || (process.argv[2] == 'ca') + exec externalHelpers.rmAll + ' ' + offHelpers.offStore() + '/*' + exec externalHelpers.rmAll + ' ' + offHelpers.objectPath() + '/*' + exec externalHelpers.rmAll + ' ' + offHelpers.objectPath() + '/../log' + +if (process.argv[2] == 'clearCache') || (process.argv[2] == 'cc') + exec externalHelpers.rmAll + ' ' + offHelpers.objectPath() + '/*' diff --git a/src/node_modules/colors/LICENSE b/src/node_modules/colors/LICENSE @@ -0,0 +1,23 @@ +Original Library + - Copyright (c) Marak Squires + +Additional Functionality + - Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) + +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.+ \ No newline at end of file diff --git a/src/node_modules/colors/ReadMe.md b/src/node_modules/colors/ReadMe.md @@ -0,0 +1,178 @@ +# colors.js [![Build Status](https://travis-ci.org/Marak/colors.js.svg?branch=master)](https://travis-ci.org/Marak/colors.js) + +## get color and style in your node.js console + +![Demo](https://raw.githubusercontent.com/Marak/colors.js/master/screenshots/colors.png) + +## Installation + + npm install colors + +## colors and styles! + +### text colors + + - black + - red + - green + - yellow + - blue + - magenta + - cyan + - white + - gray + - grey + +### background colors + + - bgBlack + - bgRed + - bgGreen + - bgYellow + - bgBlue + - bgMagenta + - bgCyan + - bgWhite + +### styles + + - reset + - bold + - dim + - italic + - underline + - inverse + - hidden + - strikethrough + +### extras + + - rainbow + - zebra + - america + - trap + - random + + +## Usage + +By popular demand, `colors` now ships with two types of usages! + +The super nifty way + +```js +var colors = require('colors'); + +console.log('hello'.green); // outputs green text +console.log('i like cake and pies'.underline.red) // outputs red underlined text +console.log('inverse the color'.inverse); // inverses the color +console.log('OMG Rainbows!'.rainbow); // rainbow +console.log('Run the trap'.trap); // Drops the bass + +``` + +or a slightly less nifty way which doesn't extend `String.prototype` + +```js +var colors = require('colors/safe'); + +console.log(colors.green('hello')); // outputs green text +console.log(colors.red.underline('i like cake and pies')) // outputs red underlined text +console.log(colors.inverse('inverse the color')); // inverses the color +console.log(colors.rainbow('OMG Rainbows!')); // rainbow +console.log(colors.trap('Run the trap')); // Drops the bass + +``` + +I prefer the first way. Some people seem to be afraid of extending `String.prototype` and prefer the second way. + +If you are writing good code you will never have an issue with the first approach. If you really don't want to touch `String.prototype`, the second usage will not touch `String` native object. + +## Disabling Colors + +To disable colors you can pass the following arguments in the command line to your application: + +```bash +node myapp.js --no-color +``` + +## Console.log [string substitution](http://nodejs.org/docs/latest/api/console.html#console_console_log_data) + +```js +var name = 'Marak'; +console.log(colors.green('Hello %s'), name); +// outputs -> 'Hello Marak' +``` + +## Custom themes + +### Using standard API + +```js + +var colors = require('colors'); + +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}); + +// outputs red text +console.log("this is an error".error); + +// outputs yellow text +console.log("this is a warning".warn); +``` + +### Using string safe API + +```js +var colors = require('colors/safe'); + +// set single property +var error = colors.red; +error('this is red'); + +// set theme +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}); + +// outputs red text +console.log(colors.error("this is an error")); + +// outputs yellow text +console.log(colors.warn("this is a warning")); + +``` + +You can also combine them: + +```javascript +var colors = require('colors'); + +colors.setTheme({ + custom: ['red', 'underline'] +}); + +console.log('test'.custom); +``` + +*Protip: There is a secret undocumented style in `colors`. If you find the style you can summon him.* diff --git a/src/node_modules/colors/examples/normal-usage.js b/src/node_modules/colors/examples/normal-usage.js @@ -0,0 +1,74 @@ +var colors = require('../lib/index'); + +console.log("First some yellow text".yellow); + +console.log("Underline that text".yellow.underline); + +console.log("Make it bold and red".red.bold); + +console.log(("Double Raindows All Day Long").rainbow) + +console.log("Drop the bass".trap) + +console.log("DROP THE RAINBOW BASS".trap.rainbow) + + +console.log('Chains are also cool.'.bold.italic.underline.red); // styles not widely supported + +console.log('So '.green + 'are'.underline + ' ' + 'inverse'.inverse + ' styles! '.yellow.bold); // styles not widely supported +console.log("Zebras are so fun!".zebra); + +// +// Remark: .strikethrough may not work with Mac OS Terminal App +// +console.log("This is " + "not".strikethrough + " fun."); + +console.log('Background color attack!'.black.bgWhite) +console.log('Use random styles on everything!'.random) +console.log('America, Heck Yeah!'.america) + + +console.log('Setting themes is useful') + +// +// Custom themes +// +console.log('Generic logging theme as JSON'.green.bold.underline); +// Load theme with JSON literal +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}); + +// outputs red text +console.log("this is an error".error); + +// outputs yellow text +console.log("this is a warning".warn); + +// outputs grey text +console.log("this is an input".input); + +console.log('Generic logging theme as file'.green.bold.underline); + +// Load a theme from file +colors.setTheme(__dirname + '/../themes/generic-logging.js'); + +// outputs red text +console.log("this is an error".error); + +// outputs yellow text +console.log("this is a warning".warn); + +// outputs grey text +console.log("this is an input".input); + +//console.log("Don't summon".zalgo)+ \ No newline at end of file diff --git a/src/node_modules/colors/examples/safe-string.js b/src/node_modules/colors/examples/safe-string.js @@ -0,0 +1,76 @@ +var colors = require('../safe'); + +console.log(colors.yellow("First some yellow text")); + +console.log(colors.yellow.underline("Underline that text")); + +console.log(colors.red.bold("Make it bold and red")); + +console.log(colors.rainbow("Double Raindows All Day Long")) + +console.log(colors.trap("Drop the bass")) + +console.log(colors.rainbow(colors.trap("DROP THE RAINBOW BASS"))); + +console.log(colors.bold.italic.underline.red('Chains are also cool.')); // styles not widely supported + + +console.log(colors.green('So ') + colors.underline('are') + ' ' + colors.inverse('inverse') + colors.yellow.bold(' styles! ')); // styles not widely supported + +console.log(colors.zebra("Zebras are so fun!")); + +console.log("This is " + colors.strikethrough("not") + " fun."); + + +console.log(colors.black.bgWhite('Background color attack!')); +console.log(colors.random('Use random styles on everything!')) +console.log(colors.america('America, Heck Yeah!')); + +console.log('Setting themes is useful') + +// +// Custom themes +// +//console.log('Generic logging theme as JSON'.green.bold.underline); +// Load theme with JSON literal +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}); + +// outputs red text +console.log(colors.error("this is an error")); + +// outputs yellow text +console.log(colors.warn("this is a warning")); + +// outputs grey text +console.log(colors.input("this is an input")); + + +// console.log('Generic logging theme as file'.green.bold.underline); + +// Load a theme from file +colors.setTheme(__dirname + '/../themes/generic-logging.js'); + +// outputs red text +console.log(colors.error("this is an error")); + +// outputs yellow text +console.log(colors.warn("this is a warning")); + +// outputs grey text +console.log(colors.input("this is an input")); + +// console.log(colors.zalgo("Don't summon him")) + + + diff --git a/src/node_modules/colors/lib/colors.js b/src/node_modules/colors/lib/colors.js @@ -0,0 +1,187 @@ +/* + +The MIT License (MIT) + +Original Library + - Copyright (c) Marak Squires + +Additional functionality + - Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) + +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. + +*/ + +var colors = {}; +module['exports'] = colors; + +colors.themes = {}; + +var ansiStyles = colors.styles = require('./styles'); +var defineProps = Object.defineProperties; + +colors.supportsColor = require('./system/supports-colors'); + +if (typeof colors.enabled === "undefined") { + colors.enabled = colors.supportsColor; +} + +colors.stripColors = colors.strip = function(str){ + return ("" + str).replace(/\x1B\[\d+m/g, ''); +}; + + +var stylize = colors.stylize = function stylize (str, style) { + if (!colors.enabled) { + return str+''; + } + + return ansiStyles[style].open + str + ansiStyles[style].close; +} + +var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; +var escapeStringRegexp = function (str) { + if (typeof str !== 'string') { + throw new TypeError('Expected a string'); + } + return str.replace(matchOperatorsRe, '\\$&'); +} + +function build(_styles) { + var builder = function builder() { + return applyStyle.apply(builder, arguments); + }; + builder._styles = _styles; + // __proto__ is used because we must return a function, but there is + // no way to create a function with a different prototype. + builder.__proto__ = proto; + return builder; +} + +var styles = (function () { + var ret = {}; + ansiStyles.grey = ansiStyles.gray; + Object.keys(ansiStyles).forEach(function (key) { + ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); + ret[key] = { + get: function () { + return build(this._styles.concat(key)); + } + }; + }); + return ret; +})(); + +var proto = defineProps(function colors() {}, styles); + +function applyStyle() { + var args = arguments; + var argsLen = args.length; + var str = argsLen !== 0 && String(arguments[0]); + if (argsLen > 1) { + for (var a = 1; a < argsLen; a++) { + str += ' ' + args[a]; + } + } + + if (!colors.enabled || !str) { + return str; + } + + var nestedStyles = this._styles; + + var i = nestedStyles.length; + while (i--) { + var code = ansiStyles[nestedStyles[i]]; + str = code.open + str.replace(code.closeRe, code.open) + code.close; + } + + return str; +} + +function applyTheme (theme) { + for (var style in theme) { + (function(style){ + colors[style] = function(str){ + if (typeof theme[style] === 'object'){ + var out = str; + for (var i in theme[style]){ + out = colors[theme[style][i]](out); + } + return out; + } + return colors[theme[style]](str); + }; + })(style) + } +} + +colors.setTheme = function (theme) { + if (typeof theme === 'string') { + try { + colors.themes[theme] = require(theme); + applyTheme(colors.themes[theme]); + return colors.themes[theme]; + } catch (err) { + console.log(err); + return err; + } + } else { + applyTheme(theme); + } +}; + +function init() { + var ret = {}; + Object.keys(styles).forEach(function (name) { + ret[name] = { + get: function () { + return build([name]); + } + }; + }); + return ret; +} + +var sequencer = function sequencer (map, str) { + var exploded = str.split(""), i = 0; + exploded = exploded.map(map); + return exploded.join(""); +}; + +// custom formatter methods +colors.trap = require('./custom/trap'); +colors.zalgo = require('./custom/zalgo'); + +// maps +colors.maps = {}; +colors.maps.america = require('./maps/america'); +colors.maps.zebra = require('./maps/zebra'); +colors.maps.rainbow = require('./maps/rainbow'); +colors.maps.random = require('./maps/random') + +for (var map in colors.maps) { + (function(map){ + colors[map] = function (str) { + return sequencer(colors.maps[map], str); + } + })(map) +} + +defineProps(colors, init());+ \ No newline at end of file diff --git a/src/node_modules/colors/lib/custom/trap.js b/src/node_modules/colors/lib/custom/trap.js @@ -0,0 +1,45 @@ +module['exports'] = function runTheTrap (text, options) { + var result = ""; + text = text || "Run the trap, drop the bass"; + text = text.split(''); + var trap = { + a: ["\u0040", "\u0104", "\u023a", "\u0245", "\u0394", "\u039b", "\u0414"], + b: ["\u00df", "\u0181", "\u0243", "\u026e", "\u03b2", "\u0e3f"], + c: ["\u00a9", "\u023b", "\u03fe"], + d: ["\u00d0", "\u018a", "\u0500" , "\u0501" ,"\u0502", "\u0503"], + e: ["\u00cb", "\u0115", "\u018e", "\u0258", "\u03a3", "\u03be", "\u04bc", "\u0a6c"], + f: ["\u04fa"], + g: ["\u0262"], + h: ["\u0126", "\u0195", "\u04a2", "\u04ba", "\u04c7", "\u050a"], + i: ["\u0f0f"], + j: ["\u0134"], + k: ["\u0138", "\u04a0", "\u04c3", "\u051e"], + l: ["\u0139"], + m: ["\u028d", "\u04cd", "\u04ce", "\u0520", "\u0521", "\u0d69"], + n: ["\u00d1", "\u014b", "\u019d", "\u0376", "\u03a0", "\u048a"], + o: ["\u00d8", "\u00f5", "\u00f8", "\u01fe", "\u0298", "\u047a", "\u05dd", "\u06dd", "\u0e4f"], + p: ["\u01f7", "\u048e"], + q: ["\u09cd"], + r: ["\u00ae", "\u01a6", "\u0210", "\u024c", "\u0280", "\u042f"], + s: ["\u00a7", "\u03de", "\u03df", "\u03e8"], + t: ["\u0141", "\u0166", "\u0373"], + u: ["\u01b1", "\u054d"], + v: ["\u05d8"], + w: ["\u0428", "\u0460", "\u047c", "\u0d70"], + x: ["\u04b2", "\u04fe", "\u04fc", "\u04fd"], + y: ["\u00a5", "\u04b0", "\u04cb"], + z: ["\u01b5", "\u0240"] + } + text.forEach(function(c){ + c = c.toLowerCase(); + var chars = trap[c] || [" "]; + var rand = Math.floor(Math.random() * chars.length); + if (typeof trap[c] !== "undefined") { + result += trap[c][rand]; + } else { + result += c; + } + }); + return result; + +} diff --git a/src/node_modules/colors/lib/custom/zalgo.js b/src/node_modules/colors/lib/custom/zalgo.js @@ -0,0 +1,104 @@ +// please no +module['exports'] = function zalgo(text, options) { + text = text || " he is here "; + var soul = { + "up" : [ + '̍', '̎', '̄', '̅', + '̿', '̑', '̆', '̐', + '͒', '͗', '͑', '̇', + '̈', '̊', '͂', '̓', + '̈', '͊', '͋', '͌', + '̃', '̂', '̌', '͐', + '̀', '́', '̋', '̏', + '̒', '̓', '̔', '̽', + '̉', 'ͣ', 'ͤ', 'ͥ', + 'ͦ', 'ͧ', 'ͨ', 'ͩ', + 'ͪ', 'ͫ', 'ͬ', 'ͭ', + 'ͮ', 'ͯ', '̾', '͛', + '͆', '̚' + ], + "down" : [ + '̖', '̗', '̘', '̙', + '̜', '̝', '̞', '̟', + '̠', '̤', '̥', '̦', + '̩', '̪', '̫', '̬', + '̭', '̮', '̯', '̰', + '̱', '̲', '̳', '̹', + '̺', '̻', '̼', 'ͅ', + '͇', '͈', '͉', '͍', + '͎', '͓', '͔', '͕', + '͖', '͙', '͚', '̣' + ], + "mid" : [ + '̕', '̛', '̀', '́', + '͘', '̡', '̢', '̧', + '̨', '̴', '̵', '̶', + '͜', '͝', '͞', + '͟', '͠', '͢', '̸', + '̷', '͡', ' ҉' + ] + }, + all = [].concat(soul.up, soul.down, soul.mid), + zalgo = {}; + + function randomNumber(range) { + var r = Math.floor(Math.random() * range); + return r; + } + + function is_char(character) { + var bool = false; + all.filter(function (i) { + bool = (i === character); + }); + return bool; + } + + + function heComes(text, options) { + var result = '', counts, l; + options = options || {}; + options["up"] = typeof options["up"] !== 'undefined' ? options["up"] : true; + options["mid"] = typeof options["mid"] !== 'undefined' ? options["mid"] : true; + options["down"] = typeof options["down"] !== 'undefined' ? options["down"] : true; + options["size"] = typeof options["size"] !== 'undefined' ? options["size"] : "maxi"; + text = text.split(''); + for (l in text) { + if (is_char(l)) { + continue; + } + result = result + text[l]; + counts = {"up" : 0, "down" : 0, "mid" : 0}; + switch (options.size) { + case 'mini': + counts.up = randomNumber(8); + counts.mid = randomNumber(2); + counts.down = randomNumber(8); + break; + case 'maxi': + counts.up = randomNumber(16) + 3; + counts.mid = randomNumber(4) + 1; + counts.down = randomNumber(64) + 3; + break; + default: + counts.up = randomNumber(8) + 1; + counts.mid = randomNumber(6) / 2; + counts.down = randomNumber(8) + 1; + break; + } + + var arr = ["up", "mid", "down"]; + for (var d in arr) { + var index = arr[d]; + for (var i = 0 ; i <= counts[index]; i++) { + if (options[index]) { + result = result + soul[index][randomNumber(soul[index].length)]; + } + } + } + } + return result; + } + // don't summon him + return heComes(text, options); +} diff --git a/src/node_modules/colors/lib/extendStringPrototype.js b/src/node_modules/colors/lib/extendStringPrototype.js @@ -0,0 +1,113 @@ +var colors = require('./colors'); + +module['exports'] = function () { + + // + // Extends prototype of native string object to allow for "foo".red syntax + // + var addProperty = function (color, func) { + String.prototype.__defineGetter__(color, func); + }; + + var sequencer = function sequencer (map, str) { + return function () { + var exploded = this.split(""), i = 0; + exploded = exploded.map(map); + return exploded.join(""); + } + }; + + addProperty('strip', function () { + return colors.strip(this); + }); + + addProperty('stripColors', function () { + return colors.strip(this); + }); + + addProperty("trap", function(){ + return colors.trap(this); + }); + + addProperty("zalgo", function(){ + return colors.zalgo(this); + }); + + addProperty("zebra", function(){ + return colors.zebra(this); + }); + + addProperty("rainbow", function(){ + return colors.rainbow(this); + }); + + addProperty("random", function(){ + return colors.random(this); + }); + + addProperty("america", function(){ + return colors.america(this); + }); + + // + // Iterate through all default styles and colors + // + var x = Object.keys(colors.styles); + x.forEach(function (style) { + addProperty(style, function () { + return colors.stylize(this, style); + }); + }); + + function applyTheme(theme) { + // + // Remark: This is a list of methods that exist + // on String that you should not overwrite. + // + var stringPrototypeBlacklist = [ + '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', 'charAt', 'constructor', + 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf', 'charCodeAt', + 'indexOf', 'lastIndexof', 'length', 'localeCompare', 'match', 'replace', 'search', 'slice', 'split', 'substring', + 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight' + ]; + + Object.keys(theme).forEach(function (prop) { + if (stringPrototypeBlacklist.indexOf(prop) !== -1) { + console.log('warn: '.red + ('String.prototype' + prop).magenta + ' is probably something you don\'t want to override. Ignoring style name'); + } + else { + if (typeof(theme[prop]) === 'string') { + colors[prop] = colors[theme[prop]]; + addProperty(prop, function () { + return colors[theme[prop]](this); + }); + } + else { + addProperty(prop, function () { + var ret = this; + for (var t = 0; t < theme[prop].length; t++) { + ret = colors[theme[prop][t]](ret); + } + return ret; + }); + } + } + }); + } + + colors.setTheme = function (theme) { + if (typeof theme === 'string') { + try { + colors.themes[theme] = require(theme); + applyTheme(colors.themes[theme]); + return colors.themes[theme]; + } catch (err) { + console.log(err); + return err; + } + } else { + applyTheme(theme); + } + }; + +};+ \ No newline at end of file diff --git a/src/node_modules/colors/lib/index.js b/src/node_modules/colors/lib/index.js @@ -0,0 +1,12 @@ +var colors = require('./colors'); +module['exports'] = colors; + +// Remark: By default, colors will add style properties to String.prototype +// +// If you don't wish to extend String.prototype you can do this instead and native String will not be touched +// +// var colors = require('colors/safe); +// colors.red("foo") +// +// +require('./extendStringPrototype')();+ \ No newline at end of file diff --git a/src/node_modules/colors/lib/maps/america.js b/src/node_modules/colors/lib/maps/america.js @@ -0,0 +1,12 @@ +var colors = require('../colors'); + +module['exports'] = (function() { + return function (letter, i, exploded) { + if(letter === " ") return letter; + switch(i%3) { + case 0: return colors.red(letter); + case 1: return colors.white(letter) + case 2: return colors.blue(letter) + } + } +})();+ \ No newline at end of file diff --git a/src/node_modules/colors/lib/maps/rainbow.js b/src/node_modules/colors/lib/maps/rainbow.js @@ -0,0 +1,13 @@ +var colors = require('../colors'); + +module['exports'] = (function () { + var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta']; //RoY G BiV + return function (letter, i, exploded) { + if (letter === " ") { + return letter; + } else { + return colors[rainbowColors[i++ % rainbowColors.length]](letter); + } + }; +})(); + diff --git a/src/node_modules/colors/lib/maps/random.js b/src/node_modules/colors/lib/maps/random.js @@ -0,0 +1,8 @@ +var colors = require('../colors'); + +module['exports'] = (function () { + var available = ['underline', 'inverse', 'grey', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta']; + return function(letter, i, exploded) { + return letter === " " ? letter : colors[available[Math.round(Math.random() * (available.length - 1))]](letter); + }; +})();+ \ No newline at end of file diff --git a/src/node_modules/colors/lib/maps/zebra.js b/src/node_modules/colors/lib/maps/zebra.js @@ -0,0 +1,5 @@ +var colors = require('../colors'); + +module['exports'] = function (letter, i, exploded) { + return i % 2 === 0 ? letter : colors.inverse(letter); +};+ \ No newline at end of file diff --git a/src/node_modules/colors/lib/styles.js b/src/node_modules/colors/lib/styles.js @@ -0,0 +1,77 @@ +/* +The MIT License (MIT) + +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) + +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. + +*/ + +var styles = {}; +module['exports'] = styles; + +var codes = { + reset: [0, 0], + + bold: [1, 22], + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29], + + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], + gray: [90, 39], + grey: [90, 39], + + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49], + + // legacy styles for colors pre v1.0.0 + blackBG: [40, 49], + redBG: [41, 49], + greenBG: [42, 49], + yellowBG: [43, 49], + blueBG: [44, 49], + magentaBG: [45, 49], + cyanBG: [46, 49], + whiteBG: [47, 49] + +}; + +Object.keys(codes).forEach(function (key) { + var val = codes[key]; + var style = styles[key] = []; + style.open = '\u001b[' + val[0] + 'm'; + style.close = '\u001b[' + val[1] + 'm'; +});+ \ No newline at end of file diff --git a/src/node_modules/colors/lib/system/supports-colors.js b/src/node_modules/colors/lib/system/supports-colors.js @@ -0,0 +1,61 @@ +/* +The MIT License (MIT) + +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) + +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. + +*/ + +var argv = process.argv; + +module.exports = (function () { + if (argv.indexOf('--no-color') !== -1 || + argv.indexOf('--color=false') !== -1) { + return false; + } + + if (argv.indexOf('--color') !== -1 || + argv.indexOf('--color=true') !== -1 || + argv.indexOf('--color=always') !== -1) { + return true; + } + + if (process.stdout && !process.stdout.isTTY) { + return false; + } + + if (process.platform === 'win32') { + return true; + } + + if ('COLORTERM' in process.env) { + return true; + } + + if (process.env.TERM === 'dumb') { + return false; + } + + if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(process.env.TERM)) { + return true; + } + + return false; +})();+ \ No newline at end of file diff --git a/src/node_modules/colors/package.json b/src/node_modules/colors/package.json @@ -0,0 +1,59 @@ +{ + "name": "colors", + "description": "get colors in your node.js console", + "version": "1.1.2", + "author": { + "name": "Marak Squires" + }, + "homepage": "https://github.com/Marak/colors.js", + "bugs": { + "url": "https://github.com/Marak/colors.js/issues" + }, + "keywords": [ + "ansi", + "terminal", + "colors" + ], + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/Marak/colors.js.git" + }, + "license": "MIT", + "scripts": { + "test": "node tests/basic-test.js && node tests/safe-test.js" + }, + "engines": { + "node": ">=0.1.90" + }, + "main": "lib", + "files": [ + "examples", + "lib", + "LICENSE", + "safe.js", + "themes" + ], + "gitHead": "8bf2ad9fa695dcb30b7e9fd83691b139fd6655c4", + "_id": "colors@1.1.2", + "_shasum": "168a4701756b6a7f51a12ce0c97bfa28c084ed63", + "_from": "colors@latest", + "_npmVersion": "2.1.8", + "_nodeVersion": "0.11.13", + "_npmUser": { + "name": "marak", + "email": "marak.squires@gmail.com" + }, + "maintainers": [ + { + "name": "marak", + "email": "marak.squires@gmail.com" + } + ], + "dist": { + "shasum": "168a4701756b6a7f51a12ce0c97bfa28c084ed63", + "tarball": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/src/node_modules/colors/safe.js b/src/node_modules/colors/safe.js @@ -0,0 +1,9 @@ +// +// Remark: Requiring this file will use the "safe" colors API which will not touch String.prototype +// +// var colors = require('colors/safe); +// colors.red("foo") +// +// +var colors = require('./lib/colors'); +module['exports'] = colors;+ \ No newline at end of file diff --git a/src/node_modules/colors/themes/generic-logging.js b/src/node_modules/colors/themes/generic-logging.js @@ -0,0 +1,12 @@ +module['exports'] = { + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +};+ \ No newline at end of file diff --git a/src/node_modules/sync-exec/.npmignore b/src/node_modules/sync-exec/.npmignore @@ -0,0 +1,4 @@ +*.kdev4 +*.log* +*.kate-swp +node_modules/ diff --git a/src/node_modules/sync-exec/LICENSE b/src/node_modules/sync-exec/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) [year] [fullname] + +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/src/node_modules/sync-exec/Makefile b/src/node_modules/sync-exec/Makefile @@ -0,0 +1,13 @@ +.PHONY: clean compile npm test + +compile: clean npm + node_modules/.bin/coffee -o js/ coffee/ + +npm: + npm install + +clean: + rm -rf js/ + +test: compile + node_modules/.bin/coffee test/example.coffee diff --git a/src/node_modules/sync-exec/README.md b/src/node_modules/sync-exec/README.md @@ -0,0 +1,40 @@ +sync-exec +========= + +An fs.execSync replacement until you get it natively from node 0.12+ + +Upgrading to 0.12.x is usually safe. At that point it will use child_process.execSync. + +You can still force the emulated version passing `{forceEmulated: true}` to the `options` argument. + + +# Advantages +Inspired by [exec-sync](https://www.npmjs.org/package/exec-sync) but comes with a few advantages: +- no libc requirement (no node-gyp compilation) +- no external dependencies +- returns the exit status code +- you can pass [execSync options](http://nodejs.org/api/child_process.html#child_process_child_process_execsync_command_options) +- multiple commands should work pretty safely + +# Installation + [sudo] npm install sync-exec + +# Signature + exec(cmd[, timeout][, options]); + +# Examples + var exec = require('sync-exec'); + + // { stdout: '1\n', + // stderr: '', + // status: 0 } + console.log(exec('echo 1')); + + // You can even pass options, just like for [child_process.exec](http://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback) + console.log(exec('ls -la', {cwd: '/etc'})); + + // Times out after 1 second, throws an error + exec('sleep 3; echo 1', 1000); + +# How it works (if you care) +Your commands STDOUT and STDERR outputs will be channeled to files, also the exit code will be saved. Synchronous file readers will start listening to these files right after. Once outputting is done, values get picked up, tmp files get deleted and values are returned to your code. diff --git a/src/node_modules/sync-exec/coffee/lib/create-pipes.coffee b/src/node_modules/sync-exec/coffee/lib/create-pipes.coffee @@ -0,0 +1,28 @@ + +fs = require 'fs' + +timeout = require './timeout' + + +# creates tmp files to pipe process info +# +# @return String path to tmp directory + +module.exports = -> + + t_limit = Date.now() + 1000 # 1 second timeout + + tmp_dir = '/tmp' + for name in ['TMPDIR', 'TMP', 'TEMP'] + tmp_dir = dir.replace /\/$/, '' if (dir = process.env[name])? + + until created + try + dir = tmp_dir + '/sync-exec-' + Math.floor Math.random() * 1000000000 + fs.mkdir dir + created = true + + timeout t_limit, 'Can not create sync-exec directory' + + # return process-tracking dir name + dir diff --git a/src/node_modules/sync-exec/coffee/lib/proxy.coffee b/src/node_modules/sync-exec/coffee/lib/proxy.coffee @@ -0,0 +1,32 @@ + +child_process = require 'child_process' + + +# Use 0.12 native functionality when available (instead of emulated blocking) +# +# @param cmd String command to execute +# @param max_wait Number millisecond timeout value +# @param options Object child_process.execSync options (like: encoding) +# +# @return Object identical to emulated: {stderr, stdout, status} + +module.exports = (cmd, max_wait, options) -> + + options.timeout = max_wait + stdout = stderr = '' + status = 0 + + t0 = Date.now() + + orig_write = process.stderr.write + process.stderr.write = -> + try + stdout = child_process.execSync cmd, options + process.stderr.write = orig_write + catch err + process.stderr.write = orig_write + if err.signal is 'SIGTERM' and t0 <= Date.now() - max_wait + throw new Error 'Timeout' + {stdout, stderr, status} = err + + {stdout, stderr, status} diff --git a/src/node_modules/sync-exec/coffee/lib/read-pipes.coffee b/src/node_modules/sync-exec/coffee/lib/read-pipes.coffee @@ -0,0 +1,40 @@ + +fs = require 'fs' + +timeout = require './timeout' + + +# Read from pipe files until they get closed/deleted +# +# @param dir String path to tmp files +# @param max_wait Number millisecond timeout value +# +# @return Object {stderr, stdout, status} + +module.exports = (dir, max_wait) -> + + t_limit = Date.now() + max_wait + + until read + try + read = true if fs.readFileSync(dir + '/done').length + timeout t_limit, 'Process execution timeout or exit flag read failure' + + until deleted + try + fs.unlinkSync dir + '/done' + deleted = true + timeout t_limit, 'Can not delete exit code file' + + result = {} + for pipe in ['stdout', 'stderr', 'status'] + result[pipe] = fs.readFileSync dir + '/' + pipe, encoding: 'utf-8' + read = true + fs.unlinkSync dir + '/' + pipe + + try + fs.rmdirSync dir + + result.status = Number result.status + + result diff --git a/src/node_modules/sync-exec/coffee/lib/timeout.coffee b/src/node_modules/sync-exec/coffee/lib/timeout.coffee @@ -0,0 +1,7 @@ + +# throw error if time limit has been exceeded + +module.exports = (limit, msg) -> + + if Date.now() > limit + throw new Error msg diff --git a/src/node_modules/sync-exec/coffee/sync-exec.coffee b/src/node_modules/sync-exec/coffee/sync-exec.coffee @@ -0,0 +1,50 @@ + +child_process = require 'child_process' + +create_pipes = require './lib/create-pipes' +proxy = require './lib/proxy' +read_pipes = require './lib/read-pipes' +timeout = require './lib/timeout' + + +# Blocking exec +# +# @param cmd String command to execute +# @param max_wait Number millisecond timeout value +# @param options Object execution options (like: encoding) +# +# @return Object {String stderr, String stdout, Number status} + +module.exports = (cmd, max_wait, options) -> + + if max_wait and typeof max_wait is 'object' + [options, max_wait] = [max_wait, null] + + options ?= {} + + unless options.hasOwnProperty 'encoding' + options.encoding = 'utf8' + + unless typeof options is 'object' and options + throw new Error 'options must be an object' + + max_wait ?= options.timeout or options.max_wait or 3600000 # 1hr default + unless not max_wait? or max_wait >= 1 + throw new Error '`options.timeout` must be >=1 millisecond' + delete options.max_wait + + # use native child_process.execSync if available (from node v0.12+) + if options.forceEmulation + delete options.forceEmulation + else if child_process.execSync + return proxy cmd, max_wait, options + + delete options.timeout + + dir = create_pipes() + cmd = '((((' + cmd + ' > ' + dir + '/stdout 2> ' + dir + '/stderr ) ' + + '&& echo $? > ' + dir + '/status) || echo $? > ' + dir + '/status) &&' + + ' echo 1 > ' + dir + '/done) || echo 1 > ' + dir + '/done' + child_process.exec cmd, options, -> + + read_pipes dir, max_wait diff --git a/src/node_modules/sync-exec/js/lib/create-pipes.js b/src/node_modules/sync-exec/js/lib/create-pipes.js @@ -0,0 +1,31 @@ +// Generated by CoffeeScript 1.9.3 +(function() { + var fs, timeout; + + fs = require('fs'); + + timeout = require('./timeout'); + + module.exports = function() { + var created, dir, i, len, name, ref, t_limit, tmp_dir; + t_limit = Date.now() + 1000; + tmp_dir = '/tmp'; + ref = ['TMPDIR', 'TMP', 'TEMP']; + for (i = 0, len = ref.length; i < len; i++) { + name = ref[i]; + if ((dir = process.env[name]) != null) { + tmp_dir = dir.replace(/\/$/, ''); + } + } + while (!created) { + try { + dir = tmp_dir + '/sync-exec-' + Math.floor(Math.random() * 1000000000); + fs.mkdir(dir); + created = true; + } catch (_error) {} + timeout(t_limit, 'Can not create sync-exec directory'); + } + return dir; + }; + +}).call(this); diff --git a/src/node_modules/sync-exec/js/lib/proxy.js b/src/node_modules/sync-exec/js/lib/proxy.js @@ -0,0 +1,33 @@ +// Generated by CoffeeScript 1.9.3 +(function() { + var child_process; + + child_process = require('child_process'); + + module.exports = function(cmd, max_wait, options) { + var err, orig_write, status, stderr, stdout, t0; + options.timeout = max_wait; + stdout = stderr = ''; + status = 0; + t0 = Date.now(); + orig_write = process.stderr.write; + process.stderr.write = function() {}; + try { + stdout = child_process.execSync(cmd, options); + process.stderr.write = orig_write; + } catch (_error) { + err = _error; + process.stderr.write = orig_write; + if (err.signal === 'SIGTERM' && t0 <= Date.now() - max_wait) { + throw new Error('Timeout'); + } + stdout = err.stdout, stderr = err.stderr, status = err.status; + } + return { + stdout: stdout, + stderr: stderr, + status: status + }; + }; + +}).call(this); diff --git a/src/node_modules/sync-exec/js/lib/read-pipes.js b/src/node_modules/sync-exec/js/lib/read-pipes.js @@ -0,0 +1,44 @@ +// Generated by CoffeeScript 1.9.3 +(function() { + var fs, timeout; + + fs = require('fs'); + + timeout = require('./timeout'); + + module.exports = function(dir, max_wait) { + var deleted, i, len, pipe, read, ref, result, t_limit; + t_limit = Date.now() + max_wait; + while (!read) { + try { + if (fs.readFileSync(dir + '/done').length) { + read = true; + } + } catch (_error) {} + timeout(t_limit, 'Process execution timeout or exit flag read failure'); + } + while (!deleted) { + try { + fs.unlinkSync(dir + '/done'); + deleted = true; + } catch (_error) {} + timeout(t_limit, 'Can not delete exit code file'); + } + result = {}; + ref = ['stdout', 'stderr', 'status']; + for (i = 0, len = ref.length; i < len; i++) { + pipe = ref[i]; + result[pipe] = fs.readFileSync(dir + '/' + pipe, { + encoding: 'utf-8' + }); + read = true; + fs.unlinkSync(dir + '/' + pipe); + } + try { + fs.rmdirSync(dir); + } catch (_error) {} + result.status = Number(result.status); + return result; + }; + +}).call(this); diff --git a/src/node_modules/sync-exec/js/lib/timeout.js b/src/node_modules/sync-exec/js/lib/timeout.js @@ -0,0 +1,9 @@ +// Generated by CoffeeScript 1.9.3 +(function() { + module.exports = function(limit, msg) { + if (Date.now() > limit) { + throw new Error(msg); + } + }; + +}).call(this); diff --git a/src/node_modules/sync-exec/js/sync-exec.js b/src/node_modules/sync-exec/js/sync-exec.js @@ -0,0 +1,48 @@ +// Generated by CoffeeScript 1.9.3 +(function() { + var child_process, create_pipes, proxy, read_pipes, timeout; + + child_process = require('child_process'); + + create_pipes = require('./lib/create-pipes'); + + proxy = require('./lib/proxy'); + + read_pipes = require('./lib/read-pipes'); + + timeout = require('./lib/timeout'); + + module.exports = function(cmd, max_wait, options) { + var dir, ref; + if (max_wait && typeof max_wait === 'object') { + ref = [max_wait, null], options = ref[0], max_wait = ref[1]; + } + if (options == null) { + options = {}; + } + if (!options.hasOwnProperty('encoding')) { + options.encoding = 'utf8'; + } + if (!(typeof options === 'object' && options)) { + throw new Error('options must be an object'); + } + if (max_wait == null) { + max_wait = options.timeout || options.max_wait || 3600000; + } + if (!((max_wait == null) || max_wait >= 1)) { + throw new Error('`options.timeout` must be >=1 millisecond'); + } + delete options.max_wait; + if (options.forceEmulation) { + delete options.forceEmulation; + } else if (child_process.execSync) { + return proxy(cmd, max_wait, options); + } + delete options.timeout; + dir = create_pipes(); + cmd = '((((' + cmd + ' > ' + dir + '/stdout 2> ' + dir + '/stderr ) ' + '&& echo $? > ' + dir + '/status) || echo $? > ' + dir + '/status) &&' + ' echo 1 > ' + dir + '/done) || echo 1 > ' + dir + '/done'; + child_process.exec(cmd, options, function() {}); + return read_pipes(dir, max_wait); + }; + +}).call(this); diff --git a/src/node_modules/sync-exec/package.json b/src/node_modules/sync-exec/package.json @@ -0,0 +1,56 @@ +{ + "name": "sync-exec", + "version": "0.6.2", + "description": "Synchronous exec with status code support. Requires no external dependencies, no need for node-gyp compilations etc.", + "main": "js/sync-exec.js", + "scripts": { + "test": "make test" + }, + "repository": { + "type": "git", + "url": "git://github.com/gvarsanyi/sync-exec.git" + }, + "keywords": [ + "exec", + "execSync", + "fs", + "sync", + "synchronous", + "status code", + "status" + ], + "author": { + "name": "Greg Varsanyi" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/gvarsanyi/sync-exec/issues" + }, + "homepage": "https://github.com/gvarsanyi/sync-exec", + "devDependencies": { + "coffee-script": "^1.9.3" + }, + "gitHead": "ecbbeee5d1ff8d2df8b9f234d8098d1dbd64ba08", + "_id": "sync-exec@0.6.2", + "_shasum": "717d22cc53f0ce1def5594362f3a89a2ebb91105", + "_from": "sync-exec@latest", + "_npmVersion": "2.11.3", + "_nodeVersion": "0.12.7", + "_npmUser": { + "name": "gvarsanyi", + "email": "gvarsanyi@gmail.com" + }, + "dist": { + "shasum": "717d22cc53f0ce1def5594362f3a89a2ebb91105", + "tarball": "https://registry.npmjs.org/sync-exec/-/sync-exec-0.6.2.tgz" + }, + "maintainers": [ + { + "name": "gvarsanyi", + "email": "gvarsanyi@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/sync-exec/-/sync-exec-0.6.2.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/src/node_modules/sync-exec/test/example.coffee b/src/node_modules/sync-exec/test/example.coffee @@ -0,0 +1,44 @@ +exec = require '../js/sync-exec' + + +delay_count = 0 +delay_check = -> + now = (new Date).getTime() + unless res1 and res2 and t + 10000 <= now < t + 12000 + throw new Error 'Timing error' + console.log 'DONE' + +t = (new Date).getTime() +setTimeout delay_check, 10 + +process.stdout.write 'Test #1 (takes ~3 seconds) ... ' +# { stdout: '1\n', +# stderr: '', +# status: 0 } +res1 = exec __dirname + '/sh/out.sh', {forceEmulation: true} +unless res1.stdout is '1\n' and res1.stderr is '' and res1.status is 0 + throw new Error 'Result #1 error:\n' + JSON.stringify res1, null, 2 +console.log 'DONE' + +# { stdout: '2\n', +# stderr: '3\n', +# status: 1 } +process.stdout.write 'Test #2 (takes ~3 seconds) ... ' +res2 = exec __dirname + '/sh/err.sh', {forceEmulation: true} +unless res2.stdout is '2\n' and res2.stderr is '3\n' and res2.status is 1 + throw new Error 'Result #2 error:\n' + JSON.stringify res2, null, 2 +console.log 'DONE' + +process.stdout.write 'Test #3 (takes ~1 second) ... ' +try + exec __dirname + '/sh/out.sh', 1000, {forceEmulation: true} + failed_to_stop = true +if failed_to_stop + throw new Error 'Failed timeout' +console.log 'DONE' + +process.stdout.write 'Test #4 (takes ~3 second) ... ' +exec './out.sh', {cwd: __dirname + '/sh', forceEmulation: true} +console.log 'DONE' + +process.stdout.write 'Test #5 ... ' # Timeout order test diff --git a/src/node_modules/sync-exec/test/sh/err.sh b/src/node_modules/sync-exec/test/sh/err.sh @@ -0,0 +1,4 @@ +sleep 3 +echo 3 1>&2 +echo 2 +false diff --git a/src/node_modules/sync-exec/test/sh/out.sh b/src/node_modules/sync-exec/test/sh/out.sh @@ -0,0 +1,2 @@ +sleep 3 +echo 1