import * as fs from 'fs' ; import * as path from 'path' ; import * as url from 'url' ; import fetch from 'node-fetch' ; import tar from 'tar' ; import bz2 from 'unbzip2-stream' ; import * as unzipper from 'unzipper' ; import * as gcc from '../src/gcc' ; function urlExt ( s ) { const u = url . parse ( s ) ; const components = u . path ?. split ( '/' ) ; if ( components && components ?. length > 0 ) { const last = components [ components ?. length - 1 ] ; const dot = last . indexOf ( '.' ) ; if ( dot >= 0 ) { return last . substr ( dot ) . toLowerCase ( ) ; } } return '' ; } export async function install ( release , directory , platform ? ) { const maxRetries = 5 ; return retryInstall ( maxRetries , release , directory , platform ) ; } async function retryInstall ( maxRetries , release , directory , platform ? ) { const distUrl = gcc . distributionUrl ( release , platform || process . platform ) ; console . log ( `downloading gcc ${ release } from ${ distUrl }` ) ; const resp = await fetch ( distUrl ) ; if ( resp . status !== 200 ) { throw new Error ( `invalid HTTP response code ${ resp . status }` ) ; } console . log ( `extracting to ${ directory }` ) ; await fs . promises . mkdir ( directory , { recursive : true } ) ; let extractor ; switch ( urlExt ( distUrl ) ) { case '.zip' : extractor = unzipper . Extract ( { path : directory } ) ; resp . body . pipe ( extractor ) ; break ; case '.tar.bz2' : extractor = tar . x ( { strip : 1 , C : directory } ) ; resp . body . pipe ( bz2 ( ) ) . pipe ( extractor ) ; break ; default : throw new Error ( `can't decompress ${ urlExt ( distUrl ) }` ) ; } await new Promise ( function ( resolve , reject ) { extractor . on ( 'close' , resolve ) ; extractor . on ( 'end' , resolve ) ; extractor . on ( 'error' , reject ) ; } ) . catch ( async function ( err ) { if ( maxRetries > 0 ) { console . log ( `retrying ${ distUrl }` ) ; return retryInstall ( maxRetries - 1 , release , directory , platform ) ; } else { throw err ; } } ) ; } function findGccWindows ( dir ) { const entries = fs . readdirSync ( dir ) ; for ( const name of entries ) { if ( name === 'arm-none-eabi-gcc.exe' ) { return dir ; } const p = path . join ( dir , name ) ; const st = fs . lstatSync ( p ) ; if ( st . isDirectory ( ) ) { const result = findGccWindows ( p ) ; if ( result !== '' ) { return result ; } } } return '' ; } export function findGcc ( root , platform ? ) { platform = platform || process . platform ; if ( platform === 'win32' ) { return findGccWindows ( root ) ; } return path . join ( root , 'bin' ) ; }