import { execAsync } from "../common/utils" ; import * as path from "path" ; import * as semver from "semver" ; export function fatal ( error ) { const e = new Error ( error ) ; ( e as any ) . fatal = true ; throw e ; } param cmd param dir param error export async function exec ( cmd , dir , error , pipeStdIn ? ) { const result = await execAsync ( cmd , { cwd : dir } , pipeStdIn ) ; if ( result . error ) { fatal ( `ERROR: Unable to ${ error }\nERROR: error during command ${ cmd }\nERROR: ${ result . error . message }` ) ; } return result . stdout ; } param cmd param dir param error export async function execNoError ( cmd , dir , pipeStdIn ? ) { const result = await execAsync ( cmd , { cwd : dir } , pipeStdIn ) ; if ( result . error ) { return undefined ; } return result . stdout ; } export class GitRepo { constructor ( public readonly resolvedRoot ) { } private async getRemotes ( ) { const result = await this . exec ( `remote -v` , `getting remotes` ) ; const remoteLines = result . split ( /\r?\n/ ) ; return remoteLines . map ( line => line . split ( /\s+/ ) ) ; } param partialUrl public async getRemote ( partialUrl ) { const lowerPartialUrl = partialUrl . toLowerCase ( ) ; const remotes = await this . getRemotes ( ) ; for ( const r of remotes ) { if ( r [ 1 ] && r [ 1 ] . toLowerCase ( ) . includes ( lowerPartialUrl ) ) { return r [ 0 ] ; } } return undefined ; } public async getCurrentSha ( ) { const result = await this . exec ( `rev-parse HEAD` , `get current sha` ) ; return result . split ( /\r?\n/ ) [ 0 ] ; } public async getShaForBranch ( branch , remote ? ) { const refspec = remote ? `refs/remotes/${ remote }/${ branch }` : `refs/heads/${ branch }` ; const result = await this . execNoError ( `show-ref ${ refspec }` ) ; if ( result ) { const line = result . split ( /\r?\n/ ) [ 0 ] ; if ( line ) { return line . split ( " " ) [ 0 ] ; } } return undefined ; } public async isBranchUpToDate ( branch , remote ) { await this . fetchBranch ( remote , branch ) ; const currentSha = await this . getShaForBranch ( branch ) ; const remoteSha = await this . getShaForBranch ( branch , remote ) ; return ( remoteSha === currentSha ) ; } public async getStatus ( ) { return await this . execNoError ( `status --porcelain` ) ; } public async getShaForTag ( tag ) { const result = await this . execNoError ( `show-ref refs/tags/${ tag }` ) ; if ( result ) { const line = result . split ( /\r?\n/ ) [ 0 ] ; if ( line ) { return line . split ( " " ) [ 0 ] ; } } return undefined ; } param tag public async addTag ( tag ) { await this . exec ( `tag ${ tag }` , `adding tag ${ tag }` ) ; } param tag public async deleteTag ( tag ) { await this . execNoError ( `tag -d ${ tag }` ) ; } /**
     * Push a tag
     *
     */ public async pushTag ( tag , remote ) { await this . exec ( `push ${ remote } ${ tag }` , `pushing tag` ) ; } /**
     * Get the current git branch name
     */ public async getCurrentBranchName ( ) { const revParseOut = await this . exec ( "rev-parse --abbrev-ref HEAD" , "get current branch" ) ; return revParseOut . split ( /\r?\n/ ) [ 0 ] ; } param branchName public async createBranch ( branchName ) { await this . exec ( `checkout -b ${ branchName }` , `create branch ${ branchName }` ) ; } param branchName public async pushBranch ( remote , fromBranchName , toBranchName ) { await this . exec ( `push ${ remote } ${ fromBranchName }:${ toBranchName }` , `push branch ${ fromBranchName }->${ toBranchName } to ${ remote }` ) ; } param branchName public async deleteBranch ( branchName ) { await this . execNoError ( `branch -D ${ branchName }` ) ; } param branchName public async switchBranch ( branchName ) { await this . exec ( `checkout ${ branchName }` , `switch branch ${ branchName }` ) ; } param message public async commit ( message , error ) { await this . exec ( `commit -a -F -` , error , message ) ; } /**
     * Fetch branch
     */ public async fetchBranch ( remote , branchName ) { return await this . exec ( `fetch ${ remote } ${ branchName }` , `fetch branch ${ branchName } from remote ${ remote }` ) ; } /**
     * Fetch Tags
     */ public async fetchTags ( ) { return await this . exec ( `fetch --tags` , `fetch tags` ) ; } param pattern public async getTags ( pattern ) { return await this . exec ( `tag -l ${ pattern }` , `get tags ${ pattern }` ) ; } param command param error private async exec ( command , error , pipeStdIn ? ) { return exec ( `git ${ command }` , this . resolvedRoot , error , pipeStdIn ) ; } param command param error private async execNoError ( command , pipeStdIn ? ) { return execNoError ( `git ${ command }` , this . resolvedRoot , pipeStdIn ) ; } } param gitRepo export async function runPolicyCheckWithFix ( gitRepo ) { console . log ( "Running Policy Check with Resolution(fix)" ) ; await exec ( `node ${ path . join ( __dirname , '..' , 'repoPolicyCheck' , 'repoPolicyCheck.js' ) } -r` , gitRepo . resolvedRoot , "policy-check:fix failed" ) ; const afterPolicyCheckStatus = await gitRepo . getStatus ( ) ; if ( afterPolicyCheckStatus !== "" ) { console . log ( "======================================================================================================" ) ; fatal ( `Policy check needed to make modifications. Please create PR for the changes and merge before retrying.\n${ afterPolicyCheckStatus }` ) ; } } export function prereleaseSatisfies ( packageVersion , range ) { return semver . satisfies ( `${ packageVersion }-zzz` , range ) ; }