import URL from 'url' ; import Git , { SimpleGit } from 'simple-git' ; import upath from 'upath' ; import { GlobalConfig } from '../../config/global' ; import { GitRefsDatasource } from '../../datasource/git-refs' ; import { logger } from '../../logger' ; import { simpleGitConfig } from '../../util/git/config' ; import { getHttpUrl , getRemoteUrlWithToken } from '../../util/git/url' ; import { regEx } from '../../util/regex' ; import type { ExtractConfig , PackageFile } from '../types' ; import { GitModule } from './types' ; async function getUrl ( git , gitModulesPath , submoduleName ) { const path = ( await Git ( simpleGitConfig ( ) ) . raw ( [ 'config' , '--file' , gitModulesPath , '--get' , `submodule.${ submoduleName }.url` , ] ) ) ?. trim ( ) ; if ( ! path ?. startsWith ( '../' ) ) { return path ; } const remoteUrl = ( await git . raw ( [ 'config' , '--get' , 'remote.origin.url' ] ) ) . trim ( ) ; return URL . resolve ( `${ remoteUrl }/` , path ) ; } const headRefRe = regEx ( /ref: refs\/heads\/(?<branch>\w+)\s/ ) ; async function getDefaultBranch ( subModuleUrl ) { const val = await Git ( ) . listRemote ( [ '--symref' , subModuleUrl , 'HEAD' ] ) ; return headRefRe . exec ( val ) ?. groups ?. branch ?? 'master' ; } async function getBranch ( gitModulesPath , submoduleName , subModuleUrl ) { return ( ( await Git ( ) . raw ( [ 'config' , '--file' , gitModulesPath , '--get' , `submodule.${ submoduleName }.branch` , ] ) ) || ( await getDefaultBranch ( subModuleUrl ) ) ) . trim ( ) ; } async function getModules ( git , gitModulesPath ) { const res = [ ] ; try { const modules = ( ( await git . raw ( [ 'config' , '--file' , gitModulesPath , '--get-regexp' , '\\.path' , ] ) ) ?? '' ) . trim ( ) . split ( regEx ( /\n/ ) ) . filter ( ( s ) => ! ! s ) ; for ( const line of modules ) { const [ , name , path ] = line . split ( regEx ( /submodule\.(.+?)\.path\s(.+)/ ) ) ; res . push ( { name , path } ) ; } } catch ( err ) { logger . warn ( { err } , 'Error getting git submodules during extract' ) ; } return res ; } export default async function extractPackageFile ( _content , fileName , config ) { const { localDir } = GlobalConfig . get ( ) ; const git = Git ( localDir ) ; const gitModulesPath = upath . join ( localDir , fileName ) ; const depNames = await getModules ( git , gitModulesPath ) ; if ( ! depNames . length ) { return null ; } const deps = [ ] ; for ( const { name , path } of depNames ) { try { const [ currentDigest ] = ( await git . subModule ( [ 'status' , path ] ) ) . trim ( ) . replace ( regEx ( /^[-+]/ ) , '' ) . split ( regEx ( /\s/ ) ) ; const subModuleUrl = await getUrl ( git , gitModulesPath , name ) ; let httpSubModuleUrl = getHttpUrl ( subModuleUrl ) ; httpSubModuleUrl = getRemoteUrlWithToken ( httpSubModuleUrl ) ; const currentValue = await getBranch ( gitModulesPath , name , httpSubModuleUrl ) ; deps . push ( { depName : path , lookupName : getHttpUrl ( subModuleUrl ) , currentValue , currentDigest , } ) ; } catch ( err ) { logger . warn ( { err } , 'Error mapping git submodules during extraction' ) ; } } return { deps , datasource : GitRefsDatasource . id } ; }