Beispiel #1
0
func updateCLI(channel string) {
	if channel == "?" {
		// do not update dev version
		return
	}
	manifest, err := getUpdateManifest(channel)
	if err != nil {
		Warn("Error updating CLI")
		PrintError(err, false)
		return
	}
	if manifest.Version == Version && manifest.Channel == Channel {
		return
	}
	LogIfError(golock.Lock(updateLockPath))
	unlock := func() {
		golock.Unlock(updateLockPath)
	}
	defer unlock()
	Errf("Updating Heroku v4 CLI to %s (%s)... ", manifest.Version, manifest.Channel)
	build := manifest.Builds[runtime.GOOS][runtime.GOARCH]
	// on windows we can't remove an existing file or remove the running binary
	// so we download the file to binName.new
	// move the running binary to binName.old (deleting any existing file first)
	// rename the downloaded file to binName
	if err := downloadBin(binPath+".new", build.URL); err != nil {
		panic(err)
	}
	if fileSha1(binPath+".new") != build.Sha1 {
		panic("SHA mismatch")
	}
	os.Remove(binPath + ".old")
	os.Rename(binPath, binPath+".old")
	if err := os.Rename(binPath+".new", binPath); err != nil {
		panic(err)
	}
	os.Remove(binPath + ".old")
	Errln("done")
	unlock()
	clearAutoupdateFile() // force full update
	reexec()              // reexec to finish updating with new code
}
Beispiel #2
0
func installPlugins(names ...string) error {
	for _, name := range names {
		lockfile := updateLockPath + "." + name
		LogIfError(golock.Lock(lockfile))
	}
	err := gode.InstallPackage(names...)
	if err != nil {
		return err
	}
	plugins := make([]*Plugin, 0, len(names))
	for _, name := range names {
		plugins = append(plugins, getPlugin(name, true))
	}
	AddPluginsToCache(plugins...)
	for _, name := range names {
		lockfile := updateLockPath + "." + name
		LogIfError(golock.Unlock(lockfile))
	}
	return nil
}
Beispiel #3
0
// Setup downloads and sets up node in the RootPath directory
func Setup() error {
	golock.Lock(lockPath)
	defer golock.Unlock(lockPath)
	t := findTarget()
	if t == nil {
		return errors.New(`node does not offer a prebuilt binary for your OS.
You'll need to compile the tarball from nodejs.org and place it in ~/.heroku/node-v` + Version)
	}
	exists, err := t.isSetup()
	if err != nil {
		return err
	}
	if exists {
		return nil
	}
	if err := t.setup(); err != nil {
		return err
	}
	SetRootPath(rootPath) // essentially sets this node as the current one
	return t.clearOldNodeInstalls()
}
Beispiel #4
0
func updatePlugins() {
	plugins := PluginNamesNotSymlinked()
	if len(plugins) == 0 {
		return
	}
	Err("Updating plugins... ")
	packages, err := gode.OutdatedPackages(plugins...)
	PrintError(err)
	if len(packages) > 0 {
		for name, version := range packages {
			lockfile := updateLockPath + "." + name
			LogIfError(golock.Lock(lockfile))
			err := gode.InstallPackage(name + "@" + version)
			PrintError(err)
			AddPluginsToCache(getPlugin(name, true))
			LogIfError(golock.Unlock(lockfile))
		}
		Errf("done. Updated %d %s.\n", len(packages), plural("package", len(packages)))
	} else {
		Errln("no plugins to update.")
	}
}
Beispiel #5
0
// lock a plugin for writing
func lockPlugin(name string) {
	LogIfError(golock.Lock(updateLockPath + "." + name))
}
Beispiel #6
0
func runFn(plugin *Plugin, topic, command string) func(ctx *Context) {
	return func(ctx *Context) {
		lockfile := updateLockPath + "." + plugin.Name
		if exists, _ := fileExists(lockfile); exists {
			golock.Lock(lockfile)
			golock.Unlock(lockfile)
		}
		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);
		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);`, 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))
		}
	}
}