func getPlugin(name string, attemptReinstall bool) *Plugin { script := ` var plugin = require('` + name + `'); if (!plugin.commands) plugin = {}; // not a real plugin var pjson = require('` + name + `/package.json'); plugin.name = pjson.name; plugin.version = pjson.version; console.log(JSON.stringify(plugin))` cmd := gode.RunScript(script) output, err := cmd.CombinedOutput() if err != nil { if attemptReinstall && strings.Contains(string(output), "Error: Cannot find module") { Errf("Error reading plugin %s. Reinstalling... ", name) if err := installPlugins(name); err != nil { panic(errors.New(string(output))) } Errln("done") return getPlugin(name, false) } Errf("Error reading plugin: %s. See %s for more information.\n", name, ErrLogPath) Logln(err, "\n", string(output)) return nil } var plugin Plugin json.Unmarshal([]byte(output), &plugin) return &plugin }
// ParsePlugin requires the plugin's node module // to get the commands and metadata func ParsePlugin(name string) (*Plugin, error) { script := ` var plugin = require('` + name + `'); if (!plugin.commands) throw new Error('Contains no commands. Is this a real plugin?'); var pjson = require('` + name + `/package.json'); plugin.name = pjson.name; plugin.version = pjson.version; console.log(JSON.stringify(plugin))` cmd := gode.RunScript(script) output, err := cmd.CombinedOutput() if err != nil { return nil, fmt.Errorf("Error reading plugin: %s\n%s\n%s", name, err, string(output)) } var plugin Plugin json.Unmarshal([]byte(output), &plugin) for _, command := range plugin.Commands { command.Plugin = plugin.Name command.Help = strings.TrimSpace(command.Help) } return &plugin, nil }
func runFn(plugin *Plugin, module, topic, command string) func(ctx *Context) { return func(ctx *Context) { lockfile := updateLockPath + "." + module if exists, _ := fileExists(lockfile); exists { golock.Lock(lockfile) golock.Unlock(lockfile) } ctx.Dev = isPluginSymlinked(module) ctxJSON, err := json.Marshal(ctx) if err != nil { panic(err) } script := fmt.Sprintf(` 'use strict'; var moduleName = '%s'; var moduleVersion = '%s'; var topic = '%s'; var command = '%s'; process.title = '%s'; var ctx = %s; ctx.version = ctx.version + ' ' + moduleName + '/' + moduleVersion + ' node-' + process.version; var logPath = %s; process.chdir(ctx.cwd); function repair (name) { console.error('Attempting to repair ' + name + '...'); require('child_process') .spawnSync('heroku', ['plugins:install', name], {stdio: [0,1,2]}); console.error('Repair complete. Try running your command again.'); } if (!ctx.dev) { process.on('uncaughtException', function (err) { console.error(' ! Error in ' + moduleName + ':') if (err.message) { console.error(' ! ' + err.message); if (err.message.indexOf('Cannot find module') != -1) { repair(moduleName); process.exit(1); } } else { console.error(' ! ' + err); } if (err.stack) { var fs = require('fs'); var log = function (line) { var d = new Date().toISOString() .replace(/T/, ' ') .replace(/-/g, '/') .replace(/\..+/, ''); fs.appendFileSync(logPath, d + ' ' + line + '\n'); } log('Error during ' + topic + ':' + command); log(err.stack); console.error(' ! See ' + logPath + ' for more info.'); } process.exit(1); }); } if (command === '') { command = null } var module = require(moduleName); var cmd = module.commands.filter(function (c) { return c.topic === topic && c.command == command; })[0]; cmd.run(ctx);`, module, plugin.Version, topic, command, processTitle(ctx), ctxJSON, strconv.Quote(ErrLogPath)) // swallow sigint since the plugin will handle it swallowSignal(os.Interrupt) cmd := gode.RunScript(script) if ctx.Flags["debugger"] == true { cmd = gode.DebugScript(script) } os.Chdir(cmd.Dir) execBin(cmd.Path, cmd.Args) } }
func runFn(plugin *Plugin, topic, command string) func(ctx *Context) { return func(ctx *Context) { readLockPlugin(plugin.Name) ctx.Dev = isPluginSymlinked(plugin.Name) ctxJSON, err := json.Marshal(ctx) if err != nil { panic(err) } title, _ := json.Marshal(processTitle(ctx)) script := fmt.Sprintf(` 'use strict'; var moduleName = '%s'; var moduleVersion = '%s'; var topic = '%s'; var command = '%s'; process.title = %s; var ctx = %s; ctx.version = ctx.version + ' ' + moduleName + '/' + moduleVersion + ' node-' + process.version; var logPath = %s; process.chdir(ctx.cwd); if (!ctx.dev) { process.on('uncaughtException', function (err) { // ignore EPIPE errors (usually from piping to head) if (err.code === "EPIPE") return; console.error(' ! Error in ' + moduleName + ':') console.error(' ! ' + err.message || err); if (err.stack) { var fs = require('fs'); var log = function (line) { var d = new Date().toISOString() .replace(/T/, ' ') .replace(/-/g, '/') .replace(/\..+/, ''); fs.appendFileSync(logPath, d + ' ' + line + '\n'); } log('Error during ' + topic + ':' + command); log(err.stack); console.error(' ! See ' + logPath + ' for more info.'); } process.exit(1); }); } if (command === '') { command = null } var module = require(moduleName); var cmd = module.commands.filter(function (c) { return c.topic === topic && c.command == command; })[0]; cmd.run(ctx);`, plugin.Name, plugin.Version, topic, command, string(title), ctxJSON, strconv.Quote(ErrLogPath)) // swallow sigint since the plugin will handle it swallowSignal(os.Interrupt) cmd := gode.RunScript(script) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if ctx.Flags["debugger"] == true { cmd = gode.DebugScript(script) } if err := cmd.Run(); err != nil { os.Exit(getExitCode(err)) } } }