Skip to content

Commit 68bbec9

Browse files
author
Sebastian McKenzie
committed
Merge branch 'master' of github.com:facebook/fbkpm
2 parents 2352ff6 + 58436d4 commit 68bbec9

File tree

3 files changed

+80
-8
lines changed

3 files changed

+80
-8
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"chalk": "^1.1.1",
1111
"cmd-shim": "^2.0.1",
1212
"commander": "^2.9.0",
13+
"death": "^1.0.0",
1314
"diff": "^2.2.1",
1415
"estraverse-fb": "^1.3.1",
1516
"ini": "^1.3.4",

src/cli/index.js

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,24 @@
1212
import buildExecuteLifecycleScript from "./commands/_execute-lifecycle-script.js";
1313
import { ConsoleReporter, JSONReporter } from "kreporters";
1414
import { MessageError } from "../errors.js";
15-
import * as network from "../util/network.js";
1615
import * as commands from "./commands/index.js";
16+
import * as constants from "../constants.js";
17+
import * as network from "../util/network.js";
18+
1719
import aliases from "./aliases.js";
1820
import Config from "../config.js";
21+
import onDeath from "death";
22+
23+
const net = require("net");
24+
const path = require("path");
25+
const fs = require("fs");
1926

20-
let loudRejection = require("loud-rejection");
21-
let commander = require("commander");
22-
let invariant = require("invariant");
23-
let pkg = require("../../package");
24-
let _ = require("lodash");
27+
let loudRejection = require("loud-rejection");
28+
let commander = require("commander");
29+
let invariant = require("invariant");
30+
let pkg = require("../../package");
31+
let _ = require("lodash");
32+
let lastWillExpressed = false;
2533

2634
loudRejection();
2735

@@ -35,6 +43,10 @@ commander.option("--modules-folder [path]", "rather than installing modules into
3543
"folder relative to the cwd, output them here");
3644
commander.option("--packages-root [path]", "rather than storing modules into a global packages root," +
3745
"store them here");
46+
commander.option(
47+
"--force-single-instance",
48+
"pause and wait if other instances are running on the same folder"
49+
);
3850
// get command name
3951
let commandName = args.splice(2, 1)[0] || "";
4052

@@ -99,12 +111,70 @@ if (network.isOffline()) {
99111
}
100112

101113
//
102-
config.init().then(function () {
114+
const run = () => {
103115
return command.run(config, reporter, commander, commander.args).then(function () {
104116
reporter.close();
105117
reporter.footer(true);
106-
process.exit();
107118
});
119+
};
120+
121+
122+
//
123+
const runEventually = () => {
124+
return new Promise((ok) => {
125+
const socketFile = path.join(config.cwd, constants.SINGLE_SOCKET_FILENAME);
126+
const clients = [];
127+
const unixServer = net.createServer((client) => {
128+
clients.push(client);
129+
});
130+
unixServer.on("error", () => {
131+
// another process exists, wait until it dies.
132+
reporter.warn("waiting until the other kpm instance finish.");
133+
134+
let socket = net.createConnection(socketFile);
135+
136+
socket.on("connect", () => {}).on("data", () => {
137+
socket.unref();
138+
ok(runEventually().then(process.exit));
139+
}).on("error", (e) => {
140+
// the process finished while we were handling the error.
141+
if (e.code === "ECONNREFUSED") {
142+
try {
143+
fs.unlinkSync(socketFile);
144+
} catch (e) {} // some other instance won the race to delete the file
145+
}
146+
147+
ok(runEventually().then(process.exit));
148+
});
149+
150+
});
151+
152+
const clean = () => {
153+
// clean after ourself.
154+
clients.forEach((client) => {
155+
client.write("closing. kthanx, bye.");
156+
});
157+
unixServer.close();
158+
process.exit();
159+
};
160+
161+
if (!lastWillExpressed) {
162+
onDeath(clean);
163+
lastWillExpressed = true;
164+
}
165+
166+
unixServer.listen(socketFile, () => {
167+
ok(run().then(clean));
168+
});
169+
});
170+
};
171+
172+
//
173+
config.init().then(() => {
174+
if (commander.forceSingleInstance) {
175+
return runEventually();
176+
}
177+
return run().then(process.exit);
108178
}).catch(function (errs) {
109179
function logError(err) {
110180
if (err instanceof MessageError) {

src/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export const MODULE_CACHE_DIRECTORY = ".fbkpm";
2121
export const LOCKFILE_FILENAME = "fbkpm.lock";
2222
export const INTEGRITY_FILENAME = ".fbkpm-integrity";
2323
export const METADATA_FILENAME = ".fbkpm-metadata.json";
24+
export const SINGLE_SOCKET_FILENAME = ".fbkpm-single-socket";
2425

2526
export const USER_AGENT = "fbkpm";
2627

0 commit comments

Comments
 (0)