1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075 |
-
-
-
-
- const fs = require("fs");
- const path = require("path");
- const { fork, spawn } = require("child_process");
- const homePath = require("user-home");
- const chalk = require("chalk");
- const shell = require("shelljs");
- shell.config.silent = true;
- const version = require("./package.json").version;
-
-
- const runtime = require("./runtime");
-
-
-
- let config;
- try {
- config = require("./config");
- } catch (err) {
- console.warn("Invalid Firepit configuration, this may be a broken build.");
- process.exit(2);
- }
-
- const isWindows = process.platform === "win32";
-
-
- const installPath = path.join(homePath, ".cache", "firebase", "tools");
- let runtimeBinsPath = path.join(homePath, ".cache", "firebase", "runtime");
-
-
- const npmArgs = [
- `--script-shell=${runtimeBinsPath}/shell${isWindows ? ".bat" : ""}`,
- `--globalconfig=${path.join(runtimeBinsPath, "npmrc")}`,
- `--userconfig=${path.join(runtimeBinsPath, "npmrc")}`,
- `--scripts-prepend-node-path=auto`
- ];
-
-
- let safeNodePath;
- const unsafeNodePath = process.argv[0];
-
-
- const flagDefinitions = [
- "file-debug",
- "log-debug",
- "disable-write",
- "runtime-check",
- "setup-check",
- "force-setup",
- "force-update",
- "ignore-embedded-cache"
- ];
-
-
- const flags = flagDefinitions.reduce((flags, name) => {
- flags[name] = process.argv.indexOf(`--tool:${name}`) !== -1;
- if (flags[name]) {
- process.argv.splice(process.argv.indexOf(`--tool:${name}`), 1);
- }
-
- return flags;
- }, {});
-
-
- if (flags["runtime-check"]) {
- console.log(`firepit invoked for runtime check, exiting subpit.`);
- return;
- }
-
- debug(`Welcome to firepit v${version}!`);
-
-
- (async () => {
-
-
- const isTopLevel = !process.env.FIREPIT_VERSION;
-
-
-
- safeNodePath = await getSafeCrossPlatformPath(isWindows, process.argv[0]);
-
-
- uninstallLegacyFirepit();
-
-
-
- if (flags["setup-check"]) {
- const bins = FindTool("firebase-tools/lib/bin/firebase");
-
- for (const bin of bins) {
- bins[bin] = await getSafeCrossPlatformPath(bins[bin]);
- }
-
- console.log(JSON.stringify({ bins }));
- return;
- }
-
-
-
-
- if (flags["force-update"]) {
- console.log(`Please wait while we clear npm's cache...`);
-
-
-
- process.argv = [
- ...process.argv.slice(0, 2),
- "is:npm",
- "cache",
- "clean",
- "--force"
- ];
-
-
-
- const code = await ImitateNPM();
-
- if (code) {
- console.log("NPM cache clearing failed, can't update.");
- process.exit(code);
- }
-
- flags["ignore-embedded-cache"] = true;
- flags["force-setup"] = true;
- console.log(`Clearing out your firebase-tools setup...`);
-
-
-
- shell.rm("-rf", installPath);
- }
-
-
-
- await createRuntimeBinaries();
-
-
-
- if (flags["force-setup"]) {
- debug("Forcing setup...");
- await SetupFirebaseTools();
- console.log("firebase-tools setup complete.");
- return;
- }
-
-
-
- if (isTopLevel && !config.headless) {
- const welcome_path = await getSafeCrossPlatformPath(
- isWindows,
- path.join(__dirname, "/welcome.js")
- );
-
- const firebaseToolsCommand = await getFirebaseToolsCommand();
-
-
-
- appendToPath(isWindows, [path.join(installPath, "bin"), runtimeBinsPath]);
-
-
-
- const shellEnv = {
- FIREPIT_VERSION: version,
- ...process.env
- };
-
- if (isWindows) {
-
-
- const shellConfig = {
- stdio: "inherit",
- env: shellEnv
- };
-
- spawn(
- "cmd",
- [
- "/k",
- [
- `doskey firebase=${firebaseToolsCommand} $*`,
- `doskey npm=${firebaseToolsCommand} is:npm $*`,
- `set prompt=${chalk.yellow("$G")}`,
- `${firebaseToolsCommand} is:node ${welcome_path} ${firebaseToolsCommand}`
- ].join(" & ")
- ],
- shellConfig
- );
-
- process.on("SIGINT", () => {
- debug("Received SIGINT. Refusing to close top-level shell.");
- });
- } else {
-
-
- process.argv = [
- ...process.argv.slice(0, 2),
- "is:node",
- welcome_path,
- firebaseToolsCommand
- ];
- const code = await ImitateNode();
-
- if (code) {
- console.log("Node failed to run welcome script.");
- process.exit(code);
- }
-
- spawn("bash", {
- env: { ...shellEnv, PS1: "\\e[0;33m> \\e[m" },
- stdio: "inherit"
- });
- }
- } else {
-
-
- SetWindowTitle("Firebase CLI");
- await firepit();
- }
-
- if (flags["file-debug"]) {
- fs.writeFileSync("firepit-log.txt", debug.log.join("\n"));
- }
- })().catch(err => {
-
-
- debug(err.toString());
- console.log(
- `This tool has encountered an error. Please file a bug on Github (https://github.com/firebase/firebase-tools/) and include firepit-log.txt`
- );
- fs.writeFileSync("firepit-log.txt", debug.log.join("\n"));
- });
-
-
- async function firepit() {
-
-
- runtimeBinsPath = await getSafeCrossPlatformPath(isWindows, runtimeBinsPath);
-
-
- process.argv[0] = safeNodePath;
- process.env.NODE = safeNodePath;
- process.env._ = safeNodePath;
-
- debug(safeNodePath);
- debug(process.argv);
-
-
- await createRuntimeBinaries();
- appendToPath(isWindows, [runtimeBinsPath]);
-
-
-
- if (process.argv.indexOf("is:npm") !== -1) {
- const code = await ImitateNPM();
- process.exit(code);
- }
-
- if (process.argv.indexOf("is:node") !== -1) {
- const code = await ImitateNode();
- process.exit(code);
- }
-
-
-
- let firebaseBins = FindTool("firebase-tools/lib/bin/firebase");
- if (!firebaseBins.length) {
- debug(`CLI not found! Invoking setup...`);
- await SetupFirebaseTools();
- firebaseBins = FindTool("firebase-tools/lib/bin/firebase");
- }
-
-
-
- const firebaseBin = firebaseBins[0];
- debug(`CLI install found at "${firebaseBin}", starting fork...`);
- const code = await ImitateFirebaseTools(firebaseBin);
- process.exit(code);
- }
-
-
-
- function ImitateNPM() {
- debug("Detected is:npm flag, calling NPM");
- const breakerIndex = process.argv.indexOf("is:npm") + 1;
- const args = [...npmArgs, ...process.argv.slice(breakerIndex)];
- debug(args.join(" "));
- return new Promise(resolve => {
- const cmd = fork(FindTool("npm/bin/npm-cli")[0], args, {
- stdio: "inherit",
- env: process.env
- });
- cmd.on("close", code => {
- debug(`faux-npm done.`);
- resolve(code);
- });
- });
- }
-
- function ImitateNode() {
- debug("Detected is:node flag, calling node");
- const breakerIndex = process.argv.indexOf("is:node") + 1;
- const nodeArgs = [...process.argv.slice(breakerIndex)];
- return new Promise(resolve => {
- const cmd = fork(nodeArgs[0], nodeArgs.slice(1), {
- stdio: "inherit",
- env: process.env
- });
- cmd.on("close", code => {
- debug(`faux-node done.`);
- resolve(code);
- });
- });
- }
-
- function ImitateFirebaseTools(binPath) {
- debug("Detected no special flags, calling firebase-tools");
- return new Promise(resolve => {
- const cmd = fork(binPath, process.argv.slice(2), {
- stdio: "inherit",
- env: { ...process.env, FIREPIT_VERSION: version }
- });
- cmd.on("close", code => {
- debug(`firebase-tools is done.`);
- resolve(code);
- });
- });
- }
-
-
-
- async function createRuntimeBinaries() {
-
-
- const runtimeBins = {
-
- shell: `"${unsafeNodePath}" ${runtimeBinsPath}/shell.js "$@"`,
- node: `"${unsafeNodePath}" ${runtimeBinsPath}/node.js "$@"`,
- npm: `"${unsafeNodePath}" "${
- FindTool("npm/bin/npm-cli")[0]
- }" ${npmArgs.join(" ")} "$@"`,
-
-
- "node.bat": `@echo off
- "${unsafeNodePath}" ${runtimeBinsPath}\\node.js %*`,
- "shell.bat": `@echo off
- "${unsafeNodePath}" ${runtimeBinsPath}\\shell.js %*`,
- "npm.bat": `@echo off
- node "${FindTool("npm/bin/npm-cli")[0]}" ${npmArgs.join(" ")} %*`,
-
-
- "shell.js": `${appendToPath.toString()}\n${getSafeCrossPlatformPath.toString()}\n(${runtime.Script_ShellJS.toString()})()`,
- "node.js": `(${runtime.Script_NodeJS.toString()})()`,
-
-
- npmrc: `prefix = ${installPath}`
- };
-
-
-
-
- try {
- shell.mkdir("-p", runtimeBinsPath);
- } catch (err) {
- debug(err);
- }
-
- if (!flags["disable-write"]) {
- Object.keys(runtimeBins).forEach(filename => {
- const runtimeBinPath = path.join(runtimeBinsPath, filename);
- try {
- shell.rm("-rf", runtimeBinPath);
- } catch (err) {
- debug(err);
- }
- fs.writeFileSync(runtimeBinPath, runtimeBins[filename]);
- shell.chmod("+x", runtimeBinPath);
- });
- }
- debug("Runtime binaries created.");
- }
-
-
- async function SetupFirebaseTools() {
-
-
- debug(`Attempting to install to "${installPath}"`);
-
- const original_argv = [...process.argv];
- const nodeModulesPath = path.join(installPath, "lib");
- const binPath = path.join(installPath, "bin");
- debug(shell.mkdir("-p", nodeModulesPath).toString());
- debug(shell.mkdir("-p", binPath).toString());
-
-
-
-
- if (!flags["ignore-embedded-cache"]) {
-
-
- debug("Using embedded cache for quick install...");
- debug(
- shell
- .cp("-R", path.join(__dirname, "vendor/*"), nodeModulesPath)
- .toString()
- );
- } else {
-
-
- debug("Using remote for slow install...");
-
- process.argv = [
- ...process.argv.slice(0, 2),
- "is:npm",
- "install",
- "-g",
- "npm",
- config.firebase_tools_package
- ];
- const code = await ImitateNPM();
- if (code) {
- console.log("Setup from remote host failed due to npm error.");
- process.exit(code);
- }
- }
-
-
-
- debug(
- shell
- .ln(
- "-sf",
- path.join(
- nodeModulesPath,
- "node_modules/firebase-tools/lib/bin/firebase.js"
- ),
- path.join(binPath, "firebase")
- )
- .toString()
- );
-
-
-
- if (!FindTool("firebase-tools/lib/bin/firebase").length) {
- console.warn(`firebase-tools setup failed.`);
- process.exit(2);
- }
-
- process.argv = original_argv;
- }
-
-
-
- function uninstallLegacyFirepit() {
-
-
-
-
-
- const isLegacyFirepit = !shell.ls(
- path.join(homePath, ".cache", "firebase", "cli")
- ).code;
-
-
-
- let installedFirebaseToolsPackage = {};
- const installedFirebaseToolsPackagePath = path.join(
- homePath,
- ".cache/firebase/tools/lib/node_modules/firebase-tools/package.json"
- );
- const firepitFirebaseToolsPackagePath = path.join(
- __dirname,
- "vendor/node_modules/firebase-tools/package.json"
- );
- debug(`Doing JSON parses for version checks at ${firepitFirebaseToolsPackagePath}`);
- debug(shell.ls(path.join(__dirname, "vendor/node_modules/")));
- const firepitFirebaseToolsPackage = JSON.parse(
- shell.cat(firepitFirebaseToolsPackagePath)
- );
- try {
- installedFirebaseToolsPackage = JSON.parse(
- shell.cat(installedFirebaseToolsPackagePath)
- );
- } catch (err) {
- debug("No existing firebase-tools install found.");
- }
-
- debug(
- `Installed ft@${installedFirebaseToolsPackage.version ||
- "none"} and packaged ft@${firepitFirebaseToolsPackage.version}`
- );
-
- const isLegacyFirebaseTools =
- installedFirebaseToolsPackage.version !==
- firepitFirebaseToolsPackage.version;
-
-
-
-
- if (!isLegacyFirepit && !isLegacyFirebaseTools) return;
- debug("Legacy firepit / firebase-tools detected, clearing it out...");
- debug(shell.rm("-rf", path.join(homePath, ".cache", "firebase")));
- }
-
- async function getFirebaseToolsCommand() {
-
-
- const isRuntime = await VerifyNodePath(safeNodePath);
- debug(`Node path ${safeNodePath} is runtime? ${isRuntime}`);
-
- let firebase_command;
- if (isRuntime) {
- const script_path = await getSafeCrossPlatformPath(
- isWindows,
- path.join(__dirname, "/firepit.js")
- );
-
- firebase_command = `${safeNodePath} ${script_path}`;
- } else {
- firebase_command = safeNodePath;
- }
- debug(firebase_command);
- return firebase_command;
- }
-
- async function VerifyNodePath(nodePath) {
-
-
- const runtimeCheckPath = await getSafeCrossPlatformPath(
- isWindows,
- path.join(__dirname, "check.js")
- );
- return new Promise(resolve => {
- const cmd = spawn(nodePath, [runtimeCheckPath, "--tool:runtime-check"], {
- shell: true
- });
-
- let result = "";
- cmd.on("error", error => {
- throw error;
- });
-
- cmd.stderr.on("data", stderr => {
- debug(`STDERR: ${stderr.toString()}`);
- });
-
- cmd.stdout.on("data", stdout => {
- debug(`STDOUT: ${stdout.toString()}`);
- result += stdout.toString();
- });
-
- cmd.on("close", code => {
- debug(
- `[VerifyNodePath] Expected "✓" from runtime got code ${code} with output "${result}"`
- );
- if (code === 0) {
- if (result.indexOf("✓") >= 0) {
- resolve(true);
- } else {
- resolve(false);
- }
- } else {
- resolve(false);
- }
- });
- });
- }
-
- function FindTool(bin) {
-
-
-
- const potentialPaths = [
- path.join(installPath, "lib/node_modules", bin),
- path.join(installPath, "node_modules", bin),
- path.join(__dirname, "node_modules", bin)
- ];
-
- return potentialPaths
- .map(path => {
- debug(`Checking for ${bin} install at ${path}`);
- if (shell.ls(path + ".js").code === 0) {
- debug(`Found ${bin} install.`);
- return path;
- }
- })
- .filter(p => p);
- }
-
- function SetWindowTitle(title) {
-
-
- if (isWindows) {
- process.title = title;
- }
- }
-
-
-
-
- async function getSafeCrossPlatformPath(isWin, path) {
-
-
- if (!isWin) return path;
-
-
-
- let command = `for %I in ("${path}") do echo %~sI`;
- return new Promise(resolve => {
- const cmd = require("child_process").spawn(`cmd`, ["/c", command], {
- shell: true
- });
-
- let result = "";
- cmd.on("error", error => {
- throw error;
- });
- cmd.stdout.on("data", stdout => {
- result += stdout.toString();
- });
-
- cmd.on("close", code => {
- if (code === 0) {
- const lines = result.split("\r\n").filter(line => line);
- const path = lines.slice(-1)[0];
- resolve(path.trim());
- } else {
- throw `Attempt to dosify path failed with code ${code}`;
- }
- });
- });
- }
-
- function appendToPath(isWin, pathsToAppend) {
-
-
- const PATH = process.env.PATH;
- const pathSeperator = isWin ? ";" : ":";
-
- process.env.PATH = [
- ...pathsToAppend,
- ...PATH.split(pathSeperator).filter(folder => folder)
- ].join(pathSeperator);
- }
-
- function debug(...msg) {
-
-
- if (!debug.log) debug.log = [];
-
- if (flags["log-debug"]) {
- msg.forEach(m => console.log(m));
- } else {
- msg.forEach(m => debug.log.push(m));
- }
- }
|