11cb0ef41Sopenharmony_ci'use strict' 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst { createWriteStream, promises: fs } = require('graceful-fs') 41cb0ef41Sopenharmony_ciconst os = require('os') 51cb0ef41Sopenharmony_ciconst { backOff } = require('exponential-backoff') 61cb0ef41Sopenharmony_ciconst tar = require('tar') 71cb0ef41Sopenharmony_ciconst path = require('path') 81cb0ef41Sopenharmony_ciconst { Transform, promises: { pipeline } } = require('stream') 91cb0ef41Sopenharmony_ciconst crypto = require('crypto') 101cb0ef41Sopenharmony_ciconst log = require('./log') 111cb0ef41Sopenharmony_ciconst semver = require('semver') 121cb0ef41Sopenharmony_ciconst { download } = require('./download') 131cb0ef41Sopenharmony_ciconst processRelease = require('./process-release') 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ciconst win = process.platform === 'win32' 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ciasync function install (gyp, argv) { 181cb0ef41Sopenharmony_ci log.stdout() 191cb0ef41Sopenharmony_ci const release = processRelease(argv, gyp, process.version, process.release) 201cb0ef41Sopenharmony_ci // Detecting target_arch based on logic from create-cnfig-gyp.js. Used on Windows only. 211cb0ef41Sopenharmony_ci const arch = win ? (gyp.opts.target_arch || gyp.opts.arch || process.arch || 'ia32') : '' 221cb0ef41Sopenharmony_ci // Used to prevent downloading tarball if only new node.lib is required on Windows. 231cb0ef41Sopenharmony_ci let shouldDownloadTarball = true 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci // Determine which node dev files version we are installing 261cb0ef41Sopenharmony_ci log.verbose('install', 'input version string %j', release.version) 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci if (!release.semver) { 291cb0ef41Sopenharmony_ci // could not parse the version string with semver 301cb0ef41Sopenharmony_ci throw new Error('Invalid version number: ' + release.version) 311cb0ef41Sopenharmony_ci } 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci if (semver.lt(release.version, '0.8.0')) { 341cb0ef41Sopenharmony_ci throw new Error('Minimum target version is `0.8.0` or greater. Got: ' + release.version) 351cb0ef41Sopenharmony_ci } 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci // 0.x.y-pre versions are not published yet and cannot be installed. Bail. 381cb0ef41Sopenharmony_ci if (release.semver.prerelease[0] === 'pre') { 391cb0ef41Sopenharmony_ci log.verbose('detected "pre" node version', release.version) 401cb0ef41Sopenharmony_ci if (!gyp.opts.nodedir) { 411cb0ef41Sopenharmony_ci throw new Error('"pre" versions of node cannot be installed, use the --nodedir flag instead') 421cb0ef41Sopenharmony_ci } 431cb0ef41Sopenharmony_ci log.verbose('--nodedir flag was passed; skipping install', gyp.opts.nodedir) 441cb0ef41Sopenharmony_ci return 451cb0ef41Sopenharmony_ci } 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci // flatten version into String 481cb0ef41Sopenharmony_ci log.verbose('install', 'installing version: %s', release.versionDir) 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci // the directory where the dev files will be installed 511cb0ef41Sopenharmony_ci const devDir = path.resolve(gyp.devDir, release.versionDir) 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci // If '--ensure' was passed, then don't *always* install the version; 541cb0ef41Sopenharmony_ci // check if it is already installed, and only install when needed 551cb0ef41Sopenharmony_ci if (gyp.opts.ensure) { 561cb0ef41Sopenharmony_ci log.verbose('install', '--ensure was passed, so won\'t reinstall if already installed') 571cb0ef41Sopenharmony_ci try { 581cb0ef41Sopenharmony_ci await fs.stat(devDir) 591cb0ef41Sopenharmony_ci } catch (err) { 601cb0ef41Sopenharmony_ci if (err.code === 'ENOENT') { 611cb0ef41Sopenharmony_ci log.verbose('install', 'version not already installed, continuing with install', release.version) 621cb0ef41Sopenharmony_ci try { 631cb0ef41Sopenharmony_ci return await go() 641cb0ef41Sopenharmony_ci } catch (err) { 651cb0ef41Sopenharmony_ci return rollback(err) 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci } else if (err.code === 'EACCES') { 681cb0ef41Sopenharmony_ci return eaccesFallback(err) 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci throw err 711cb0ef41Sopenharmony_ci } 721cb0ef41Sopenharmony_ci log.verbose('install', 'version is already installed, need to check "installVersion"') 731cb0ef41Sopenharmony_ci const installVersionFile = path.resolve(devDir, 'installVersion') 741cb0ef41Sopenharmony_ci let installVersion = 0 751cb0ef41Sopenharmony_ci try { 761cb0ef41Sopenharmony_ci const ver = await fs.readFile(installVersionFile, 'ascii') 771cb0ef41Sopenharmony_ci installVersion = parseInt(ver, 10) || 0 781cb0ef41Sopenharmony_ci } catch (err) { 791cb0ef41Sopenharmony_ci if (err.code !== 'ENOENT') { 801cb0ef41Sopenharmony_ci throw err 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci } 831cb0ef41Sopenharmony_ci log.verbose('got "installVersion"', installVersion) 841cb0ef41Sopenharmony_ci log.verbose('needs "installVersion"', gyp.package.installVersion) 851cb0ef41Sopenharmony_ci if (installVersion < gyp.package.installVersion) { 861cb0ef41Sopenharmony_ci log.verbose('install', 'version is no good; reinstalling') 871cb0ef41Sopenharmony_ci try { 881cb0ef41Sopenharmony_ci return await go() 891cb0ef41Sopenharmony_ci } catch (err) { 901cb0ef41Sopenharmony_ci return rollback(err) 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci } 931cb0ef41Sopenharmony_ci log.verbose('install', 'version is good') 941cb0ef41Sopenharmony_ci if (win) { 951cb0ef41Sopenharmony_ci log.verbose('on Windows; need to check node.lib') 961cb0ef41Sopenharmony_ci const nodeLibPath = path.resolve(devDir, arch, 'node.lib') 971cb0ef41Sopenharmony_ci try { 981cb0ef41Sopenharmony_ci await fs.stat(nodeLibPath) 991cb0ef41Sopenharmony_ci } catch (err) { 1001cb0ef41Sopenharmony_ci if (err.code === 'ENOENT') { 1011cb0ef41Sopenharmony_ci log.verbose('install', `version not already installed for ${arch}, continuing with install`, release.version) 1021cb0ef41Sopenharmony_ci try { 1031cb0ef41Sopenharmony_ci shouldDownloadTarball = false 1041cb0ef41Sopenharmony_ci return await go() 1051cb0ef41Sopenharmony_ci } catch (err) { 1061cb0ef41Sopenharmony_ci return rollback(err) 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci } else if (err.code === 'EACCES') { 1091cb0ef41Sopenharmony_ci return eaccesFallback(err) 1101cb0ef41Sopenharmony_ci } 1111cb0ef41Sopenharmony_ci throw err 1121cb0ef41Sopenharmony_ci } 1131cb0ef41Sopenharmony_ci } 1141cb0ef41Sopenharmony_ci } else { 1151cb0ef41Sopenharmony_ci try { 1161cb0ef41Sopenharmony_ci return await go() 1171cb0ef41Sopenharmony_ci } catch (err) { 1181cb0ef41Sopenharmony_ci return rollback(err) 1191cb0ef41Sopenharmony_ci } 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci async function copyDirectory (src, dest) { 1231cb0ef41Sopenharmony_ci try { 1241cb0ef41Sopenharmony_ci await fs.stat(src) 1251cb0ef41Sopenharmony_ci } catch { 1261cb0ef41Sopenharmony_ci throw new Error(`Missing source directory for copy: ${src}`) 1271cb0ef41Sopenharmony_ci } 1281cb0ef41Sopenharmony_ci await fs.mkdir(dest, { recursive: true }) 1291cb0ef41Sopenharmony_ci const entries = await fs.readdir(src, { withFileTypes: true }) 1301cb0ef41Sopenharmony_ci for (const entry of entries) { 1311cb0ef41Sopenharmony_ci if (entry.isDirectory()) { 1321cb0ef41Sopenharmony_ci await copyDirectory(path.join(src, entry.name), path.join(dest, entry.name)) 1331cb0ef41Sopenharmony_ci } else if (entry.isFile()) { 1341cb0ef41Sopenharmony_ci // with parallel installs, copying files may cause file errors on 1351cb0ef41Sopenharmony_ci // Windows so use an exponential backoff to resolve collisions 1361cb0ef41Sopenharmony_ci await backOff(async () => { 1371cb0ef41Sopenharmony_ci try { 1381cb0ef41Sopenharmony_ci await fs.copyFile(path.join(src, entry.name), path.join(dest, entry.name)) 1391cb0ef41Sopenharmony_ci } catch (err) { 1401cb0ef41Sopenharmony_ci // if ensure, check if file already exists and that's good enough 1411cb0ef41Sopenharmony_ci if (gyp.opts.ensure && err.code === 'EBUSY') { 1421cb0ef41Sopenharmony_ci try { 1431cb0ef41Sopenharmony_ci await fs.stat(path.join(dest, entry.name)) 1441cb0ef41Sopenharmony_ci return 1451cb0ef41Sopenharmony_ci } catch {} 1461cb0ef41Sopenharmony_ci } 1471cb0ef41Sopenharmony_ci throw err 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci }) 1501cb0ef41Sopenharmony_ci } else { 1511cb0ef41Sopenharmony_ci throw new Error('Unexpected file directory entry type') 1521cb0ef41Sopenharmony_ci } 1531cb0ef41Sopenharmony_ci } 1541cb0ef41Sopenharmony_ci } 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci async function go () { 1571cb0ef41Sopenharmony_ci log.verbose('ensuring devDir is created', devDir) 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci // first create the dir for the node dev files 1601cb0ef41Sopenharmony_ci try { 1611cb0ef41Sopenharmony_ci const created = await fs.mkdir(devDir, { recursive: true }) 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci if (created) { 1641cb0ef41Sopenharmony_ci log.verbose('created devDir', created) 1651cb0ef41Sopenharmony_ci } 1661cb0ef41Sopenharmony_ci } catch (err) { 1671cb0ef41Sopenharmony_ci if (err.code === 'EACCES') { 1681cb0ef41Sopenharmony_ci return eaccesFallback(err) 1691cb0ef41Sopenharmony_ci } 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci throw err 1721cb0ef41Sopenharmony_ci } 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci // now download the node tarball 1751cb0ef41Sopenharmony_ci const tarPath = gyp.opts.tarball 1761cb0ef41Sopenharmony_ci let extractErrors = false 1771cb0ef41Sopenharmony_ci let extractCount = 0 1781cb0ef41Sopenharmony_ci const contentShasums = {} 1791cb0ef41Sopenharmony_ci const expectShasums = {} 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci // checks if a file to be extracted from the tarball is valid. 1821cb0ef41Sopenharmony_ci // only .h header files and the gyp files get extracted 1831cb0ef41Sopenharmony_ci function isValid (path) { 1841cb0ef41Sopenharmony_ci const isValid = valid(path) 1851cb0ef41Sopenharmony_ci if (isValid) { 1861cb0ef41Sopenharmony_ci log.verbose('extracted file from tarball', path) 1871cb0ef41Sopenharmony_ci extractCount++ 1881cb0ef41Sopenharmony_ci } else { 1891cb0ef41Sopenharmony_ci // invalid 1901cb0ef41Sopenharmony_ci log.silly('ignoring from tarball', path) 1911cb0ef41Sopenharmony_ci } 1921cb0ef41Sopenharmony_ci return isValid 1931cb0ef41Sopenharmony_ci } 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_ci function onwarn (code, message) { 1961cb0ef41Sopenharmony_ci extractErrors = true 1971cb0ef41Sopenharmony_ci log.error('error while extracting tarball', code, message) 1981cb0ef41Sopenharmony_ci } 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci // download the tarball and extract! 2011cb0ef41Sopenharmony_ci // Ommited on Windows if only new node.lib is required 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci // on Windows there can be file errors from tar if parallel installs 2041cb0ef41Sopenharmony_ci // are happening (not uncommon with multiple native modules) so 2051cb0ef41Sopenharmony_ci // extract the tarball to a temp directory first and then copy over 2061cb0ef41Sopenharmony_ci const tarExtractDir = win ? await fs.mkdtemp(path.join(os.tmpdir(), 'node-gyp-tmp-')) : devDir 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci try { 2091cb0ef41Sopenharmony_ci if (shouldDownloadTarball) { 2101cb0ef41Sopenharmony_ci if (tarPath) { 2111cb0ef41Sopenharmony_ci await tar.extract({ 2121cb0ef41Sopenharmony_ci file: tarPath, 2131cb0ef41Sopenharmony_ci strip: 1, 2141cb0ef41Sopenharmony_ci filter: isValid, 2151cb0ef41Sopenharmony_ci onwarn, 2161cb0ef41Sopenharmony_ci cwd: tarExtractDir 2171cb0ef41Sopenharmony_ci }) 2181cb0ef41Sopenharmony_ci } else { 2191cb0ef41Sopenharmony_ci try { 2201cb0ef41Sopenharmony_ci const res = await download(gyp, release.tarballUrl) 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci if (res.status !== 200) { 2231cb0ef41Sopenharmony_ci throw new Error(`${res.status} response downloading ${release.tarballUrl}`) 2241cb0ef41Sopenharmony_ci } 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci await pipeline( 2271cb0ef41Sopenharmony_ci res.body, 2281cb0ef41Sopenharmony_ci // content checksum 2291cb0ef41Sopenharmony_ci new ShaSum((_, checksum) => { 2301cb0ef41Sopenharmony_ci const filename = path.basename(release.tarballUrl).trim() 2311cb0ef41Sopenharmony_ci contentShasums[filename] = checksum 2321cb0ef41Sopenharmony_ci log.verbose('content checksum', filename, checksum) 2331cb0ef41Sopenharmony_ci }), 2341cb0ef41Sopenharmony_ci tar.extract({ 2351cb0ef41Sopenharmony_ci strip: 1, 2361cb0ef41Sopenharmony_ci cwd: tarExtractDir, 2371cb0ef41Sopenharmony_ci filter: isValid, 2381cb0ef41Sopenharmony_ci onwarn 2391cb0ef41Sopenharmony_ci }) 2401cb0ef41Sopenharmony_ci ) 2411cb0ef41Sopenharmony_ci } catch (err) { 2421cb0ef41Sopenharmony_ci // something went wrong downloading the tarball? 2431cb0ef41Sopenharmony_ci if (err.code === 'ENOTFOUND') { 2441cb0ef41Sopenharmony_ci throw new Error('This is most likely not a problem with node-gyp or the package itself and\n' + 2451cb0ef41Sopenharmony_ci 'is related to network connectivity. In most cases you are behind a proxy or have bad \n' + 2461cb0ef41Sopenharmony_ci 'network settings.') 2471cb0ef41Sopenharmony_ci } 2481cb0ef41Sopenharmony_ci throw err 2491cb0ef41Sopenharmony_ci } 2501cb0ef41Sopenharmony_ci } 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ci // invoked after the tarball has finished being extracted 2531cb0ef41Sopenharmony_ci if (extractErrors || extractCount === 0) { 2541cb0ef41Sopenharmony_ci throw new Error('There was a fatal problem while downloading/extracting the tarball') 2551cb0ef41Sopenharmony_ci } 2561cb0ef41Sopenharmony_ci 2571cb0ef41Sopenharmony_ci log.verbose('tarball', 'done parsing tarball') 2581cb0ef41Sopenharmony_ci } 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_ci const installVersionPath = path.resolve(tarExtractDir, 'installVersion') 2611cb0ef41Sopenharmony_ci await Promise.all([ 2621cb0ef41Sopenharmony_ci // need to download node.lib 2631cb0ef41Sopenharmony_ci ...(win ? [downloadNodeLib()] : []), 2641cb0ef41Sopenharmony_ci // write the "installVersion" file 2651cb0ef41Sopenharmony_ci fs.writeFile(installVersionPath, gyp.package.installVersion + '\n'), 2661cb0ef41Sopenharmony_ci // Only download SHASUMS.txt if we downloaded something in need of SHA verification 2671cb0ef41Sopenharmony_ci ...(!tarPath || win ? [downloadShasums()] : []) 2681cb0ef41Sopenharmony_ci ]) 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci log.verbose('download contents checksum', JSON.stringify(contentShasums)) 2711cb0ef41Sopenharmony_ci // check content shasums 2721cb0ef41Sopenharmony_ci for (const k in contentShasums) { 2731cb0ef41Sopenharmony_ci log.verbose('validating download checksum for ' + k, '(%s == %s)', contentShasums[k], expectShasums[k]) 2741cb0ef41Sopenharmony_ci if (contentShasums[k] !== expectShasums[k]) { 2751cb0ef41Sopenharmony_ci throw new Error(k + ' local checksum ' + contentShasums[k] + ' not match remote ' + expectShasums[k]) 2761cb0ef41Sopenharmony_ci } 2771cb0ef41Sopenharmony_ci } 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci // copy over the files from the temp tarball extract directory to devDir 2801cb0ef41Sopenharmony_ci if (tarExtractDir !== devDir) { 2811cb0ef41Sopenharmony_ci await copyDirectory(tarExtractDir, devDir) 2821cb0ef41Sopenharmony_ci } 2831cb0ef41Sopenharmony_ci } finally { 2841cb0ef41Sopenharmony_ci if (tarExtractDir !== devDir) { 2851cb0ef41Sopenharmony_ci try { 2861cb0ef41Sopenharmony_ci // try to cleanup temp dir 2871cb0ef41Sopenharmony_ci await fs.rm(tarExtractDir, { recursive: true }) 2881cb0ef41Sopenharmony_ci } catch { 2891cb0ef41Sopenharmony_ci log.warn('failed to clean up temp tarball extract directory') 2901cb0ef41Sopenharmony_ci } 2911cb0ef41Sopenharmony_ci } 2921cb0ef41Sopenharmony_ci } 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ci async function downloadShasums () { 2951cb0ef41Sopenharmony_ci log.verbose('check download content checksum, need to download `SHASUMS256.txt`...') 2961cb0ef41Sopenharmony_ci log.verbose('checksum url', release.shasumsUrl) 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci const res = await download(gyp, release.shasumsUrl) 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_ci if (res.status !== 200) { 3011cb0ef41Sopenharmony_ci throw new Error(`${res.status} status code downloading checksum`) 3021cb0ef41Sopenharmony_ci } 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci for (const line of (await res.text()).trim().split('\n')) { 3051cb0ef41Sopenharmony_ci const items = line.trim().split(/\s+/) 3061cb0ef41Sopenharmony_ci if (items.length !== 2) { 3071cb0ef41Sopenharmony_ci return 3081cb0ef41Sopenharmony_ci } 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci // 0035d18e2dcf9aad669b1c7c07319e17abfe3762 ./node-v0.11.4.tar.gz 3111cb0ef41Sopenharmony_ci const name = items[1].replace(/^\.\//, '') 3121cb0ef41Sopenharmony_ci expectShasums[name] = items[0] 3131cb0ef41Sopenharmony_ci } 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_ci log.verbose('checksum data', JSON.stringify(expectShasums)) 3161cb0ef41Sopenharmony_ci } 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci async function downloadNodeLib () { 3191cb0ef41Sopenharmony_ci log.verbose('on Windows; need to download `' + release.name + '.lib`...') 3201cb0ef41Sopenharmony_ci const dir = path.resolve(tarExtractDir, arch) 3211cb0ef41Sopenharmony_ci const targetLibPath = path.resolve(dir, release.name + '.lib') 3221cb0ef41Sopenharmony_ci const { libUrl, libPath } = release[arch] 3231cb0ef41Sopenharmony_ci const name = `${arch} ${release.name}.lib` 3241cb0ef41Sopenharmony_ci log.verbose(name, 'dir', dir) 3251cb0ef41Sopenharmony_ci log.verbose(name, 'url', libUrl) 3261cb0ef41Sopenharmony_ci 3271cb0ef41Sopenharmony_ci await fs.mkdir(dir, { recursive: true }) 3281cb0ef41Sopenharmony_ci log.verbose('streaming', name, 'to:', targetLibPath) 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_ci const res = await download(gyp, libUrl) 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_ci // Since only required node.lib is downloaded throw error if it is not fetched 3331cb0ef41Sopenharmony_ci if (res.status !== 200) { 3341cb0ef41Sopenharmony_ci throw new Error(`${res.status} status code downloading ${name}`) 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci return pipeline( 3381cb0ef41Sopenharmony_ci res.body, 3391cb0ef41Sopenharmony_ci new ShaSum((_, checksum) => { 3401cb0ef41Sopenharmony_ci contentShasums[libPath] = checksum 3411cb0ef41Sopenharmony_ci log.verbose('content checksum', libPath, checksum) 3421cb0ef41Sopenharmony_ci }), 3431cb0ef41Sopenharmony_ci createWriteStream(targetLibPath) 3441cb0ef41Sopenharmony_ci ) 3451cb0ef41Sopenharmony_ci } // downloadNodeLib() 3461cb0ef41Sopenharmony_ci } // go() 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci /** 3491cb0ef41Sopenharmony_ci * Checks if a given filename is "valid" for this installation. 3501cb0ef41Sopenharmony_ci */ 3511cb0ef41Sopenharmony_ci 3521cb0ef41Sopenharmony_ci function valid (file) { 3531cb0ef41Sopenharmony_ci // header files 3541cb0ef41Sopenharmony_ci const extname = path.extname(file) 3551cb0ef41Sopenharmony_ci return extname === '.h' || extname === '.gypi' 3561cb0ef41Sopenharmony_ci } 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_ci async function rollback (err) { 3591cb0ef41Sopenharmony_ci log.warn('install', 'got an error, rolling back install') 3601cb0ef41Sopenharmony_ci // roll-back the install if anything went wrong 3611cb0ef41Sopenharmony_ci await gyp.commands.remove([release.versionDir]) 3621cb0ef41Sopenharmony_ci throw err 3631cb0ef41Sopenharmony_ci } 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_ci /** 3661cb0ef41Sopenharmony_ci * The EACCES fallback is a workaround for npm's `sudo` behavior, where 3671cb0ef41Sopenharmony_ci * it drops the permissions before invoking any child processes (like 3681cb0ef41Sopenharmony_ci * node-gyp). So what happens is the "nobody" user doesn't have 3691cb0ef41Sopenharmony_ci * permission to create the dev dir. As a fallback, make the tmpdir() be 3701cb0ef41Sopenharmony_ci * the dev dir for this installation. This is not ideal, but at least 3711cb0ef41Sopenharmony_ci * the compilation will succeed... 3721cb0ef41Sopenharmony_ci */ 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci async function eaccesFallback (err) { 3751cb0ef41Sopenharmony_ci const noretry = '--node_gyp_internal_noretry' 3761cb0ef41Sopenharmony_ci if (argv.indexOf(noretry) !== -1) { 3771cb0ef41Sopenharmony_ci throw err 3781cb0ef41Sopenharmony_ci } 3791cb0ef41Sopenharmony_ci const tmpdir = os.tmpdir() 3801cb0ef41Sopenharmony_ci gyp.devDir = path.resolve(tmpdir, '.node-gyp') 3811cb0ef41Sopenharmony_ci let userString = '' 3821cb0ef41Sopenharmony_ci try { 3831cb0ef41Sopenharmony_ci // os.userInfo can fail on some systems, it's not critical here 3841cb0ef41Sopenharmony_ci userString = ` ("${os.userInfo().username}")` 3851cb0ef41Sopenharmony_ci } catch (e) {} 3861cb0ef41Sopenharmony_ci log.warn('EACCES', 'current user%s does not have permission to access the dev dir "%s"', userString, devDir) 3871cb0ef41Sopenharmony_ci log.warn('EACCES', 'attempting to reinstall using temporary dev dir "%s"', gyp.devDir) 3881cb0ef41Sopenharmony_ci if (process.cwd() === tmpdir) { 3891cb0ef41Sopenharmony_ci log.verbose('tmpdir == cwd', 'automatically will remove dev files after to save disk space') 3901cb0ef41Sopenharmony_ci gyp.todo.push({ name: 'remove', args: argv }) 3911cb0ef41Sopenharmony_ci } 3921cb0ef41Sopenharmony_ci return gyp.commands.install([noretry].concat(argv)) 3931cb0ef41Sopenharmony_ci } 3941cb0ef41Sopenharmony_ci} 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ciclass ShaSum extends Transform { 3971cb0ef41Sopenharmony_ci constructor (callback) { 3981cb0ef41Sopenharmony_ci super() 3991cb0ef41Sopenharmony_ci this._callback = callback 4001cb0ef41Sopenharmony_ci this._digester = crypto.createHash('sha256') 4011cb0ef41Sopenharmony_ci } 4021cb0ef41Sopenharmony_ci 4031cb0ef41Sopenharmony_ci _transform (chunk, _, callback) { 4041cb0ef41Sopenharmony_ci this._digester.update(chunk) 4051cb0ef41Sopenharmony_ci callback(null, chunk) 4061cb0ef41Sopenharmony_ci } 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_ci _flush (callback) { 4091cb0ef41Sopenharmony_ci this._callback(null, this._digester.digest('hex')) 4101cb0ef41Sopenharmony_ci callback() 4111cb0ef41Sopenharmony_ci } 4121cb0ef41Sopenharmony_ci} 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_cimodule.exports = install 4151cb0ef41Sopenharmony_cimodule.exports.usage = 'Install node development files for the specified node version.' 416