You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
3.4 KiB
148 lines
3.4 KiB
/* eslint-disable unicorn/no-process-exit */
|
|
|
|
// Native
|
|
import fs from 'fs'
|
|
import path from 'path'
|
|
import zlib from 'zlib'
|
|
|
|
// Packages
|
|
import onDeath from 'death'
|
|
import fetch from 'node-fetch'
|
|
import retry from 'async-retry'
|
|
|
|
// Utilities
|
|
import plusxSync from './chmod'
|
|
import {
|
|
disableProgress,
|
|
enableProgress,
|
|
info,
|
|
showProgress,
|
|
warn
|
|
} from './log'
|
|
|
|
fetch.Promise = Promise
|
|
global.Promise = Promise
|
|
const now = path.join(__dirname, 'now')
|
|
const targetWin32 = path.join(__dirname, 'now.exe')
|
|
const target = process.platform === 'win32' ? targetWin32 : now
|
|
const partial = target + '.partial'
|
|
|
|
const packagePath = path.join(__dirname, '../../package.json')
|
|
const packageJSON = JSON.parse(fs.readFileSync(packagePath, 'utf8'))
|
|
|
|
const platformToName = {
|
|
darwin: 'now-macos',
|
|
linux: 'now-linux',
|
|
win32: 'now-win.exe'
|
|
}
|
|
|
|
async function main() {
|
|
try {
|
|
fs.writeFileSync(
|
|
now,
|
|
'#!/usr/bin/env node\n' +
|
|
'console.log("Please wait until the \'now\' installation completes!")\n'
|
|
)
|
|
} catch (err) {
|
|
if (err.code === 'EACCES') {
|
|
warn(
|
|
'Please try installing now CLI again with the `--unsafe-perm` option.'
|
|
)
|
|
info('Example: `npm i -g --unsafe-perm now`')
|
|
|
|
process.exit()
|
|
}
|
|
|
|
throw err
|
|
}
|
|
|
|
onDeath(() => {
|
|
fs.writeFileSync(
|
|
now,
|
|
'#!/usr/bin/env node\n' +
|
|
'console.log("The \'now\' installation did not complete successfully.")\n' +
|
|
'console.log("Please run \'npm i -g now\' to reinstall!")\n'
|
|
)
|
|
process.exit()
|
|
})
|
|
|
|
info('For the source code, check out: https://github.com/zeit/now-cli')
|
|
|
|
// Print an empty line
|
|
console.log('')
|
|
|
|
await retry(async () => {
|
|
enableProgress('Downloading now CLI ' + packageJSON.version)
|
|
showProgress(0)
|
|
|
|
try {
|
|
const name = platformToName[process.platform]
|
|
const url = `https://cdn.zeit.co/releases/now-cli/${packageJSON.version}/${name}`
|
|
const resp = await fetch(url, { compress: false })
|
|
|
|
if (resp.status !== 200) {
|
|
throw new Error(resp.statusText + ' ' + url)
|
|
}
|
|
|
|
const size = resp.headers.get('content-length')
|
|
const ws = fs.createWriteStream(partial)
|
|
|
|
await new Promise((resolve, reject) => {
|
|
let bytesRead = 0
|
|
|
|
resp.body
|
|
.on('error', reject)
|
|
.on('data', chunk => {
|
|
bytesRead += chunk.length
|
|
showProgress(100 * bytesRead / size)
|
|
})
|
|
|
|
const gunzip = zlib.createGunzip()
|
|
|
|
gunzip
|
|
.on('error', reject)
|
|
|
|
resp.body.pipe(gunzip).pipe(ws)
|
|
|
|
ws
|
|
.on('error', reject)
|
|
.on('close', () => {
|
|
showProgress(100)
|
|
resolve()
|
|
})
|
|
})
|
|
} finally {
|
|
disableProgress()
|
|
}
|
|
}, {
|
|
retries: 500,
|
|
onRetry: (err) => console.error(err)
|
|
})
|
|
|
|
fs.renameSync(partial, target)
|
|
|
|
if (process.platform === 'win32') {
|
|
// Now.exe is executed only
|
|
fs.unlinkSync(now)
|
|
// Workaround for https://github.com/npm/cmd-shim/pull/25
|
|
const gitBashFile = path.join(process.env.APPDATA, 'npm/now')
|
|
fs.writeFileSync(
|
|
gitBashFile,
|
|
'#!/bin/sh\n' +
|
|
'basedir=$(dirname "$(echo "$0" | sed -e \'s,\\\\,/,g\')")\n' +
|
|
'\n' +
|
|
'case `uname` in\n' +
|
|
' *CYGWIN*) basedir=`cygpath -w "$basedir"`;;\n' +
|
|
'esac\n' +
|
|
'\n' +
|
|
fs.readFileSync(gitBashFile, 'utf8')
|
|
)
|
|
} else {
|
|
plusxSync(now)
|
|
}
|
|
}
|
|
|
|
main().catch(err => {
|
|
console.error(err)
|
|
process.exit(2)
|
|
})
|
|
|