import * as datasourceGithubTags from '../../datasource/github-tags' ; import { logger } from '../../logger' ; import { SkipReason } from '../../types' ; import { regEx } from '../../util/regex' ; import type { PackageDependency , PackageFile } from '../types' ; import type { UrlPathParsedResult } from './types' ; import { isSpace , removeComments , skip } from './util' ; function parseSha256 ( idx , content ) { let i = idx ; i += 'sha256' . length ; i = skip ( i , content , ( c ) => isSpace ( c ) ) ; if ( content [ i ] !== '"' && content [ i ] !== "'" ) { return null ; } i += 1 ; const j = skip ( i , content , ( c ) => c !== '"' && c !== "'" ) ; const sha256 = content . slice ( i , j ) ; return sha256 ; } function extractSha256 ( content ) { const sha256RegExp = regEx ( /(^|\s)sha256(\s)/ ) ; let i = content . search ( sha256RegExp ) ; if ( isSpace ( content [ i ] ) ) { i += 1 ; } return parseSha256 ( i , content ) ; } function parseUrl ( idx , content ) { 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 j = skip ( i , content , ( c ) => c !== '"' && c !== "'" && ! isSpace ( c ) ) ; const url = content . slice ( i , j ) ; return url ; } function extractUrl ( content ) { const urlRegExp = regEx ( /(^|\s)url(\s)/ ) ; let i = content . search ( urlRegExp ) ; if ( i === - 1 ) { return null ; } if ( isSpace ( content [ i ] ) ) { i += 1 ; } return parseUrl ( i , content ) ; } export function parseUrlPath ( urlStr ) { if ( ! urlStr ) { return null ; } try { const url = new URL ( urlStr ) ; if ( url . hostname !== 'github.com' ) { return null ; } let s = url . pathname . split ( '/' ) ; s = s . filter ( ( val ) => val ) ; const ownerName = s [ 0 ] ; const repoName = s [ 1 ] ; let currentValue ; if ( s [ 2 ] === 'archive' ) { currentValue = s [ 3 ] ; const targz = currentValue . slice ( currentValue . length - 7 , currentValue . length ) ; if ( targz === '.tar.gz' ) { currentValue = currentValue . substring ( 0 , currentValue . length - 7 ) ; } } else if ( s [ 2 ] === 'releases' && s [ 3 ] === 'download' ) { currentValue = s [ 4 ] ; } if ( ! currentValue ) { return null ; } return { currentValue , ownerName , repoName } ; } catch ( _ ) { return null ; } } function parseClassHeader ( idx , content ) { let i = idx ; i += 'class' . length ; i = skip ( i , content , ( c ) => isSpace ( c ) ) ; let j = skip ( i , content , ( c ) => ! isSpace ( c ) && c !== '<' ) ; const className = content . slice ( i , j ) ; i = j ; i = skip ( i , content , ( c ) => isSpace ( c ) ) ; if ( content [ i ] === '<' ) { i += 1 ; } else { return null ; } i = skip ( i , content , ( c ) => isSpace ( c ) ) ; j = skip ( i , content , ( c ) => ! isSpace ( c ) ) ; if ( content . slice ( i , j ) !== 'Formula' ) { return null ; } return className ; } function extractClassName ( content ) { const classRegExp = regEx ( /(^|\s)class\s/ ) ; let i = content . search ( classRegExp ) ; if ( isSpace ( content [ i ] ) ) { i += 1 ; } return parseClassHeader ( i , content ) ; } export function extractPackageFile ( content ) { logger . trace ( 'extractPackageFile()' ) ; const cleanContent = removeComments ( content ) ; const className = extractClassName ( cleanContent ) ; if ( ! className ) { logger . debug ( 'Invalid class definition' ) ; return null ; } const url = extractUrl ( cleanContent ) ; if ( ! url ) { logger . debug ( 'Invalid URL field' ) ; } const urlPathResult = parseUrlPath ( url ) ; let skipReason ; let currentValue = null ; let ownerName = null ; let repoName = null ; if ( urlPathResult ) { currentValue = urlPathResult . currentValue ; ownerName = urlPathResult . ownerName ; repoName = urlPathResult . repoName ; } else { logger . debug ( 'Error: Unsupported URL field' ) ; skipReason = SkipReason . UnsupportedUrl ; } const sha256 = extractSha256 ( cleanContent ) ; if ( ! sha256 || sha256 . length !== 64 ) { logger . debug ( 'Error: Invalid sha256 field' ) ; skipReason = SkipReason . InvalidSha256 ; } const dep = { depName : `${ ownerName }/${ repoName }` , managerData : { ownerName , repoName , sha256 , url } , currentValue , datasource : datasourceGithubTags . id , } ; if ( skipReason ) { dep . skipReason = skipReason ; if ( skipReason === 'unsupported-url' ) { dep . depName = className ; dep . datasource = null ; } } const deps = [ dep ] ; return { deps } ; }