aboutsummaryrefslogtreecommitdiff
path: root/node_modules/fb-watchman/index.js
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.h.kronqvist@gmail.com>2022-03-05 19:02:27 +0200
committerJoel Kronqvist <joel.h.kronqvist@gmail.com>2022-03-05 19:02:27 +0200
commit5d309ff52cd399a6b71968a6b9a70c8ac0b98981 (patch)
tree360f7eb50f956e2367ef38fa1fc6ac7ac5258042 /node_modules/fb-watchman/index.js
parentb500a50f1b97d93c98b36ed9a980f8188d648147 (diff)
downloadLYLLRuoka-5d309ff52cd399a6b71968a6b9a70c8ac0b98981.tar.gz
LYLLRuoka-5d309ff52cd399a6b71968a6b9a70c8ac0b98981.zip
Added node_modules for the updating to work properly.
Diffstat (limited to 'node_modules/fb-watchman/index.js')
-rw-r--r--node_modules/fb-watchman/index.js322
1 files changed, 322 insertions, 0 deletions
diff --git a/node_modules/fb-watchman/index.js b/node_modules/fb-watchman/index.js
new file mode 100644
index 0000000..9f46e16
--- /dev/null
+++ b/node_modules/fb-watchman/index.js
@@ -0,0 +1,322 @@
+/* Copyright 2014-present Facebook, Inc.
+ * Licensed under the Apache License, Version 2.0 */
+
+'use strict';
+
+var net = require('net');
+var EE = require('events').EventEmitter;
+var util = require('util');
+var childProcess = require('child_process');
+var bser = require('bser');
+
+// We'll emit the responses to these when they get sent down to us
+var unilateralTags = ['subscription', 'log'];
+
+/**
+ * @param options An object with the following optional keys:
+ * * 'watchmanBinaryPath' (string) Absolute path to the watchman binary.
+ * If not provided, the Client locates the binary using the PATH specified
+ * by the node child_process's default env.
+ */
+function Client(options) {
+ var self = this;
+ EE.call(this);
+
+ this.watchmanBinaryPath = 'watchman';
+ if (options && options.watchmanBinaryPath) {
+ this.watchmanBinaryPath = options.watchmanBinaryPath.trim();
+ };
+ this.commands = [];
+}
+util.inherits(Client, EE);
+
+module.exports.Client = Client;
+
+// Try to send the next queued command, if any
+Client.prototype.sendNextCommand = function() {
+ if (this.currentCommand) {
+ // There's a command pending response, don't send this new one yet
+ return;
+ }
+
+ this.currentCommand = this.commands.shift();
+ if (!this.currentCommand) {
+ // No further commands are queued
+ return;
+ }
+
+ this.socket.write(bser.dumpToBuffer(this.currentCommand.cmd));
+}
+
+Client.prototype.cancelCommands = function(why) {
+ var error = new Error(why);
+
+ // Steal all pending commands before we start cancellation, in
+ // case something decides to schedule more commands
+ var cmds = this.commands;
+ this.commands = [];
+
+ if (this.currentCommand) {
+ cmds.unshift(this.currentCommand);
+ this.currentCommand = null;
+ }
+
+ // Synthesize an error condition for any commands that were queued
+ cmds.forEach(function(cmd) {
+ cmd.cb(error);
+ });
+}
+
+Client.prototype.connect = function() {
+ var self = this;
+
+ function makeSock(sockname) {
+ // bunser will decode the watchman BSER protocol for us
+ self.bunser = new bser.BunserBuf();
+ // For each decoded line:
+ self.bunser.on('value', function(obj) {
+ // Figure out if this is a unliteral response or if it is the
+ // response portion of a request-response sequence. At the time
+ // of writing, there are only two possible unilateral responses.
+ var unilateral = false;
+ for (var i = 0; i < unilateralTags.length; i++) {
+ var tag = unilateralTags[i];
+ if (tag in obj) {
+ unilateral = tag;
+ }
+ }
+
+ if (unilateral) {
+ self.emit(unilateral, obj);
+ } else if (self.currentCommand) {
+ var cmd = self.currentCommand;
+ self.currentCommand = null;
+ if ('error' in obj) {
+ var error = new Error(obj.error);
+ error.watchmanResponse = obj;
+ cmd.cb(error);
+ } else {
+ cmd.cb(null, obj);
+ }
+ }
+
+ // See if we can dispatch the next queued command, if any
+ self.sendNextCommand();
+ });
+ self.bunser.on('error', function(err) {
+ self.emit('error', err);
+ });
+
+ self.socket = net.createConnection(sockname);
+ self.socket.on('connect', function() {
+ self.connecting = false;
+ self.emit('connect');
+ self.sendNextCommand();
+ });
+ self.socket.on('error', function(err) {
+ self.connecting = false;
+ self.emit('error', err);
+ });
+ self.socket.on('data', function(buf) {
+ if (self.bunser) {
+ self.bunser.append(buf);
+ }
+ });
+ self.socket.on('end', function() {
+ self.socket = null;
+ self.bunser = null;
+ self.cancelCommands('The watchman connection was closed');
+ self.emit('end');
+ });
+ }
+
+ // triggers will export the sock path to the environment.
+ // If we're invoked in such a way, we can simply pick up the
+ // definition from the environment and avoid having to fork off
+ // a process to figure it out
+ if (process.env.WATCHMAN_SOCK) {
+ makeSock(process.env.WATCHMAN_SOCK);
+ return;
+ }
+
+ // We need to ask the client binary where to find it.
+ // This will cause the service to start for us if it isn't
+ // already running.
+ var args = ['--no-pretty', 'get-sockname'];
+
+ // We use the more elaborate spawn rather than exec because there
+ // are some error cases on Windows where process spawning can hang.
+ // It is desirable to pipe stderr directly to stderr live so that
+ // we can discover the problem.
+ var proc = null;
+ var spawnFailed = false;
+
+ function spawnError(error) {
+ if (spawnFailed) {
+ // For ENOENT, proc 'close' will also trigger with a negative code,
+ // let's suppress that second error.
+ return;
+ }
+ spawnFailed = true;
+ if (error.errno === 'EACCES') {
+ error.message = 'The Watchman CLI is installed but cannot ' +
+ 'be spawned because of a permission problem';
+ } else if (error.errno === 'ENOENT') {
+ error.message = 'Watchman was not found in PATH. See ' +
+ 'https://facebook.github.io/watchman/docs/install.html ' +
+ 'for installation instructions';
+ }
+ console.error('Watchman: ', error.message);
+ self.emit('error', error);
+ }
+
+ try {
+ proc = childProcess.spawn(this.watchmanBinaryPath, args, {
+ stdio: ['ignore', 'pipe', 'pipe']
+ });
+ } catch (error) {
+ spawnError(error);
+ return;
+ }
+
+ var stdout = [];
+ var stderr = [];
+ proc.stdout.on('data', function(data) {
+ stdout.push(data);
+ });
+ proc.stderr.on('data', function(data) {
+ data = data.toString('utf8');
+ stderr.push(data);
+ console.error(data);
+ });
+ proc.on('error', function(error) {
+ spawnError(error);
+ });
+
+ proc.on('close', function (code, signal) {
+ if (code !== 0) {
+ spawnError(new Error(
+ self.watchmanBinaryPath + ' ' + args.join(' ') +
+ ' returned with exit code=' + code + ', signal=' +
+ signal + ', stderr= ' + stderr.join('')));
+ return;
+ }
+ try {
+ var obj = JSON.parse(stdout.join(''));
+ if ('error' in obj) {
+ var error = new Error(obj.error);
+ error.watchmanResponse = obj;
+ self.emit('error', error);
+ return;
+ }
+ makeSock(obj.sockname);
+ } catch (e) {
+ self.emit('error', e);
+ }
+ });
+}
+
+Client.prototype.command = function(args, done) {
+ done = done || function() {};
+
+ // Queue up the command
+ this.commands.push({cmd: args, cb: done});
+
+ // Establish a connection if we don't already have one
+ if (!this.socket) {
+ if (!this.connecting) {
+ this.connecting = true;
+ this.connect();
+ return;
+ }
+ return;
+ }
+
+ // If we're already connected and idle, try sending the command immediately
+ this.sendNextCommand();
+}
+
+var cap_versions = {
+ "cmd-watch-del-all": "3.1.1",
+ "cmd-watch-project": "3.1",
+ "relative_root": "3.3",
+ "term-dirname": "3.1",
+ "term-idirname": "3.1",
+ "wildmatch": "3.7",
+}
+
+// Compares a vs b, returns < 0 if a < b, > 0 if b > b, 0 if a == b
+function vers_compare(a, b) {
+ a = a.split('.');
+ b = b.split('.');
+ for (var i = 0; i < 3; i++) {
+ var d = parseInt(a[i] || '0') - parseInt(b[i] || '0');
+ if (d != 0) {
+ return d;
+ }
+ }
+ return 0; // Equal
+}
+
+function have_cap(vers, name) {
+ if (name in cap_versions) {
+ return vers_compare(vers, cap_versions[name]) >= 0;
+ }
+ return false;
+}
+
+// This is a helper that we expose for testing purposes
+Client.prototype._synthesizeCapabilityCheck = function(
+ resp, optional, required) {
+ resp.capabilities = {}
+ var version = resp.version;
+ optional.forEach(function (name) {
+ resp.capabilities[name] = have_cap(version, name);
+ });
+ required.forEach(function (name) {
+ var have = have_cap(version, name);
+ resp.capabilities[name] = have;
+ if (!have) {
+ resp.error = 'client required capability `' + name +
+ '` is not supported by this server';
+ }
+ });
+ return resp;
+}
+
+Client.prototype.capabilityCheck = function(caps, done) {
+ var optional = caps.optional || [];
+ var required = caps.required || [];
+ var self = this;
+ this.command(['version', {
+ optional: optional,
+ required: required
+ }], function (error, resp) {
+ if (error) {
+ done(error);
+ return;
+ }
+ if (!('capabilities' in resp)) {
+ // Server doesn't support capabilities, so we need to
+ // synthesize the results based on the version
+ resp = self._synthesizeCapabilityCheck(resp, optional, required);
+ if (resp.error) {
+ error = new Error(resp.error);
+ error.watchmanResponse = resp;
+ done(error);
+ return;
+ }
+ }
+ done(null, resp);
+ });
+}
+
+// Close the connection to the service
+Client.prototype.end = function() {
+ this.cancelCommands('The client was ended');
+ if (this.socket) {
+ this.socket.end();
+ this.socket = null;
+ }
+ this.bunser = null;
+}