|
#!/usr/bin/env zx --experimental |
|
/* vim: syntax=javascript |
|
*/ |
|
|
|
// Setting verbose to false so it won't print the executing command which make it hard for scripts |
|
// TODO - should allow setting verbose from command line |
|
const isDebug = process.env.DEBUG && process.env.DEBUG !== "false"; |
|
const ogVerbose = $.verbose; |
|
$.verbose = ogVerbose; |
|
|
|
async function getAllNetworkServices() { |
|
// Get all network setup |
|
const { stdout } = await $`networksetup -listallnetworkservices`; |
|
|
|
const networkServicesName = stdout.split("\n").filter(Boolean); |
|
|
|
const networkServices = {}; |
|
|
|
for (let i = 0; i < networkServicesName.length; i++) { |
|
const networkService = networkServicesName[i]; |
|
|
|
try { |
|
const info = await getNetworkServiceInfo(networkService); |
|
|
|
if (info.IPv6 === "automatic") { |
|
networkServices[networkService] = info; |
|
} |
|
} catch (e) { |
|
if (i === 0) { |
|
// First line is: `An asterisk (*) denotes that a network service is disabled.` |
|
// But I'm not sure if this is always the case |
|
// so checking just in case |
|
continue; |
|
} |
|
|
|
printError( |
|
"Error getting info for network service: " + networkService, |
|
e |
|
); |
|
} |
|
} |
|
|
|
return networkServices; |
|
} |
|
|
|
async function getNetworkServiceInfo(name) { |
|
// Get all network setup |
|
const { stdout } = await $`networksetup -getinfo ${name}`; |
|
|
|
const info = Object.fromEntries( |
|
stdout |
|
.split("\n") |
|
.filter(Boolean) |
|
.map((item) => item.split(":").map((item) => item.trim())) |
|
); |
|
|
|
if (!info.IPv6) { |
|
console.error( |
|
`${chalk.red( |
|
`No IPv6 info for ${chalk.bold(name)}` |
|
)} stdout:\n${stdout}\n` |
|
); |
|
throw new Error("No IPv6 info"); |
|
} |
|
|
|
info.IPv6 = info.IPv6.toLowerCase(); |
|
|
|
return info; |
|
} |
|
|
|
async function disableIPv6ForInterfaces(allInterfaces) { |
|
for (const interfaceName in allInterfaces) { |
|
await $`networksetup -setv6off ${interfaceName}`; |
|
} |
|
} |
|
|
|
async function revertAutomaticIPv6ForInterfaces(allInterfaces) { |
|
const failedInterfaces = []; |
|
for (const interfaceName in allInterfaces) { |
|
try { |
|
await $`networksetup -setv6automatic ${interfaceName}`; |
|
} catch (e) { |
|
failedInterfaces.push(interfaceName); |
|
console.error(e); |
|
} |
|
} |
|
|
|
if (failedInterfaces.length) { |
|
console.error( |
|
`${chalk.red( |
|
`Failed to revert IPv6 to automatic for the following interfaces:` |
|
)} ${failedInterfaces.map((item) => `"${item}"`).join(", ")}` |
|
); |
|
} |
|
} |
|
|
|
async function bundleInstall(dryRun = false) { |
|
const cwd = process.cwd(); |
|
const currentScript = __filename; |
|
|
|
const indexOfCurrentScript = process.argv.findIndex( |
|
(item) => path.join(cwd, item) === currentScript || (path.isAbsolute(item) && item === currentScript) |
|
); |
|
|
|
if (indexOfCurrentScript === -1) { |
|
throw new Error("Couldn't find current script in argv"); |
|
} |
|
|
|
// Only get argument after the current script (like node <zx-path> --experimental <this-script>) |
|
const bundleInstallArgs = process.argv.slice(indexOfCurrentScript + 1); |
|
|
|
if (!dryRun) { |
|
// Run bundle install with this script arguments |
|
await $`bundle install ${bundleInstallArgs}`; |
|
} |
|
} |
|
|
|
// Dry run bundle install |
|
await bundleInstall(true); |
|
|
|
// Avoiding having a lot of output when not debugging |
|
$.verbose = isDebug; |
|
const allInterfacesWithIPv6AsAutomatic = await getAllNetworkServices(); |
|
$.verbose = ogVerbose; |
|
|
|
try { |
|
$.verbose = isDebug; |
|
await disableIPv6ForInterfaces(allInterfacesWithIPv6AsAutomatic); |
|
|
|
$.verbose = true; |
|
await bundleInstall(); |
|
} finally { |
|
$.verbose = true; |
|
|
|
const msg = chalk.bold( |
|
"Gonna revert the following interfaces back to automatic:" |
|
); |
|
const interfaces = Object.keys(allInterfacesWithIPv6AsAutomatic) |
|
.map((item) => `- ${item}`) |
|
.join("\n"); |
|
console.log(`${msg}\n${interfaces}`); |
|
|
|
await revertAutomaticIPv6ForInterfaces(allInterfacesWithIPv6AsAutomatic); |
|
} |
|
|
|
function printError(message, error) { |
|
if (!isDebug && !ogVerbose) { |
|
return; |
|
} |
|
|
|
console.error(message, error); |
|
} |