format import fs from 'fs' ; import path from 'path' ; const binaryExtensions = [ '.png' , '.jar' , '.keystore' ] ; type ContentChangedCallbackOption = 'identical' | 'changed' | 'new' | null ; param srcPath param destPath param replacements param contentChangedCallback function copyAndReplace ( srcPath , destPath , replacements , contentChangedCallback ) { if ( fs . lstatSync ( srcPath ) . isDirectory ( ) ) { if ( ! fs . existsSync ( destPath ) ) { fs . mkdirSync ( destPath ) ; } return ; } const extension = path . extname ( srcPath ) ; if ( binaryExtensions . indexOf ( extension ) !== - 1 ) { let shouldOverwrite = 'overwrite' ; if ( contentChangedCallback ) { const newContentBuffer = fs . readFileSync ( srcPath ) ; let contentChanged = 'identical' ; try { const origContentBuffer = fs . readFileSync ( destPath ) ; if ( Buffer . compare ( origContentBuffer , newContentBuffer ) !== 0 ) { contentChanged = 'changed' ; } } catch ( err ) { if ( err . code === 'ENOENT' ) { contentChanged = 'new' ; } else { throw err ; } } shouldOverwrite = contentChangedCallback ( destPath , contentChanged ) ; } if ( shouldOverwrite === 'overwrite' ) { copyBinaryFile ( srcPath , destPath , ( err ) => { if ( err ) { throw err ; } } ) ; } } else { const srcPermissions = fs . statSync ( srcPath ) . mode ; let content = fs . readFileSync ( srcPath , 'utf8' ) ; Object . keys ( replacements ) . forEach ( ( regex ) => { content = content . replace ( new RegExp ( regex , 'g' ) , replacements [ regex ] ) ; } ) ; let shouldOverwrite = 'overwrite' ; if ( contentChangedCallback ) { let contentChanged = 'identical' ; try { const origContent = fs . readFileSync ( destPath , 'utf8' ) ; if ( content !== origContent ) { contentChanged = 'changed' ; } } catch ( err ) { if ( err . code === 'ENOENT' ) { contentChanged = 'new' ; } else { throw err ; } } shouldOverwrite = contentChangedCallback ( destPath , contentChanged ) ; } if ( shouldOverwrite === 'overwrite' ) { fs . writeFileSync ( destPath , content , { encoding : 'utf8' , mode : srcPermissions , } ) ; } } } /**
 * Same as 'cp' on Unix. Don't do any replacements.
 */ function copyBinaryFile ( srcPath , destPath , cb ) { let cbCalled = false ; const srcPermissions = fs . statSync ( srcPath ) . mode ; const readStream = fs . createReadStream ( srcPath ) ; readStream . on ( 'error' , ( err ) => { done ( err ) ; } ) ; const writeStream = fs . createWriteStream ( destPath , { mode : srcPermissions , } ) ; writeStream . on ( 'error' , ( err ) => { done ( err ) ; } ) ; writeStream . on ( 'close' , ( ) => { done ( ) ; } ) ; readStream . pipe ( writeStream ) ; function done ( err ? ) { if ( ! cbCalled ) { cb ( err ) ; cbCalled = true ; } } } export default copyAndReplace ;