import hasha from 'hasha' ; import semver from 'semver' ; import { logger } from '../../logger' ; import { Http } from '../../util/http' ; import type { UpdateDependencyConfig } from '../types' ; import { parseUrlPath } from './extract' ; import { isSpace , removeComments , skip } from './util' ; const http = new Http ( 'homebrew' ) ; function replaceUrl ( idx , content , oldUrl , newUrl ) { let i = idx ; i += 'url' . length ; i = skip ( i , content , ( c ) => isSpace ( c ) ) ; const chr = content [ i ] ; if ( chr !== '"' && chr !== "'" ) { return null ; } i += 1 ; const newContent = content . substring ( 0 , i ) + content . substring ( i ) . replace ( oldUrl , newUrl ) ; return newContent ; } function getUrlTestContent ( content , oldUrl , newUrl ) { const urlRegExp = /(^|\s)url(\s)/ ; const cleanContent = removeComments ( content ) ; let j = cleanContent . search ( urlRegExp ) ; if ( isSpace ( cleanContent [ j ] ) ) { j += 1 ; } const testContent = replaceUrl ( j , cleanContent , oldUrl , newUrl ) ; return testContent ; } function updateUrl ( content , oldUrl , newUrl ) { const urlRegExp = /(^|\s)url(\s)/ ; let i = content . search ( urlRegExp ) ; if ( i === - 1 ) { return null ; } if ( isSpace ( content [ i ] ) ) { i += 1 ; } let newContent = replaceUrl ( i , content , oldUrl , newUrl ) ; const testContent = getUrlTestContent ( content , oldUrl , newUrl ) ; if ( ! newContent || ! testContent ) { return null ; } while ( removeComments ( newContent ) !== testContent ) { i += 'url' . length ; i += content . substring ( i ) . search ( urlRegExp ) ; if ( isSpace ( content [ i ] ) ) { i += 1 ; } newContent = replaceUrl ( i , content , oldUrl , newUrl ) ; } return newContent ; } function replaceSha256 ( idx , content , oldSha256 , newSha256 ) { let i = idx ; i += 'sha256' . length ; i = skip ( i , content , ( c ) => isSpace ( c ) ) ; const chr = content [ i ] ; if ( chr !== '"' && chr !== "'" ) { return null ; } i += 1 ; const newContent = content . substring ( 0 , i ) + content . substring ( i ) . replace ( oldSha256 , newSha256 ) ; return newContent ; } function getSha256TestContent ( content , oldSha256 , newSha256 ) { const sha256RegExp = /(^|\s)sha256(\s)/ ; const cleanContent = removeComments ( content ) ; let j = cleanContent . search ( sha256RegExp ) ; if ( isSpace ( cleanContent [ j ] ) ) { j += 1 ; } const testContent = replaceSha256 ( j , cleanContent , oldSha256 , newSha256 ) ; return testContent ; } function updateSha256 ( content , oldSha256 , newSha256 ) { const sha256RegExp = /(^|\s)sha256(\s)/ ; let i = content . search ( sha256RegExp ) ; if ( i === - 1 ) { return null ; } if ( isSpace ( content [ i ] ) ) { i += 1 ; } let newContent = replaceSha256 ( i , content , oldSha256 , newSha256 ) ; const testContent = getSha256TestContent ( content , oldSha256 , newSha256 ) ; if ( ! newContent || ! testContent ) { return null ; } while ( removeComments ( newContent ) !== testContent ) { i += 'sha256' . length ; i += content . substring ( i ) . search ( sha256RegExp ) ; if ( isSpace ( content [ i ] ) ) { i += 1 ; } newContent = replaceSha256 ( i , content , oldSha256 , newSha256 ) ; } return newContent ; } export async function updateDependency ( { fileContent , upgrade , } ) { logger . trace ( 'updateDependency()' ) ; let newUrl ; const oldParsedUrlPath = parseUrlPath ( upgrade . managerData . url ) ; if ( ! oldParsedUrlPath ) { logger . debug ( `Failed to update - upgrade.managerData.url is invalid ${ upgrade . depName }` ) ; return fileContent ; } let newSha256 ; try { const ownerName = String ( upgrade . managerData . ownerName ) ; const repoName = String ( upgrade . managerData . repoName ) ; newUrl = `https://github.com/${ ownerName }/${ repoName }/releases/download/${ upgrade . newValue }/${ repoName }-${ String ( semver . coerce ( upgrade . newValue ) ) }.tar.gz` ; newSha256 = await hasha . fromStream ( http . stream ( newUrl ) , { algorithm : 'sha256' , } ) ; } catch ( errOuter ) { logger . debug ( `Failed to download release download for ${ upgrade . depName } - trying archive instead` ) ; try { const ownerName = String ( upgrade . managerData . ownerName ) ; const repoName = String ( upgrade . managerData . repoName ) ; newUrl = `https://github.com/${ ownerName }/${ repoName }/archive/${ upgrade . newValue }.tar.gz` ; newSha256 = await hasha . fromStream ( http . stream ( newUrl ) , { algorithm : 'sha256' , } ) ; } catch ( errInner ) { logger . debug ( `Failed to download archive download for ${ upgrade . depName } - update failed` ) ; return fileContent ; } } if ( ! newSha256 ) { logger . debug ( `Failed to generate new sha256 for ${ upgrade . depName } - update failed` ) ; return fileContent ; } const newParsedUrlPath = parseUrlPath ( newUrl ) ; if ( ! newParsedUrlPath ) { logger . debug ( `Failed to update url for dependency ${ upgrade . depName }` ) ; return fileContent ; } if ( upgrade . newValue !== newParsedUrlPath . currentValue ) { logger . debug ( `Failed to update url for dependency ${ upgrade . depName }` ) ; return fileContent ; } let newContent = updateUrl ( fileContent , upgrade . managerData . url , newUrl ) ; if ( ! newContent ) { logger . debug ( `Failed to update url for dependency ${ upgrade . depName }` ) ; return fileContent ; } newContent = updateSha256 ( newContent , upgrade . managerData . sha256 , newSha256 ) ; if ( ! newContent ) { logger . debug ( `Failed to update sha256 for dependency ${ upgrade . depName }` ) ; return fileContent ; } return newContent ; }