@ -162,6 +162,7 @@ class GitAuthHelper {
this . sshKeyPath = '' ;
this . sshKeyPath = '' ;
this . sshKnownHostsPath = '' ;
this . sshKnownHostsPath = '' ;
this . temporaryHomePath = '' ;
this . temporaryHomePath = '' ;
this . credentialsConfigPath = '' ; // Path to separate credentials config file in RUNNER_TEMP
this . git = gitCommandManager ;
this . git = gitCommandManager ;
this . settings = gitSourceSettings || { } ;
this . settings = gitSourceSettings || { } ;
// Token auth header
// Token auth header
@ -229,15 +230,17 @@ class GitAuthHelper {
configureGlobalAuth ( ) {
configureGlobalAuth ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
// 'configureTempGlobalConfig' noops if already set, just returns the path
// 'configureTempGlobalConfig' noops if already set, just returns the path
const newGitConfigPath = yield this . configureTempGlobalConfig ( ) ;
yield this . configureTempGlobalConfig ( ) ;
try {
try {
// Configure the token
// Configure the token
yield this . configureToken ( newGitConfigPath , true ) ;
yield this . configureToken ( true ) ;
// Configure HTTPS instead of SSH
// Configure HTTPS instead of SSH
yield this . git . tryConfigUnset ( this . insteadOfKey , true ) ;
yield this . git . tryConfigUnset ( this . insteadOfKey , true ) ;
if ( ! this . settings . sshKey ) {
if ( ! this . settings . sshKey ) {
for ( const insteadOfValue of this . insteadOfValues ) {
for ( const insteadOfValue of this . insteadOfValues ) {
yield this . git . config ( this . insteadOfKey , insteadOfValue , true , true ) ;
yield this . git . config ( this . insteadOfKey , insteadOfValue , true , // globalConfig?
true // add?
) ;
}
}
}
}
}
}
@ -252,19 +255,34 @@ class GitAuthHelper {
configureSubmoduleAuth ( ) {
configureSubmoduleAuth ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
// Remove possible previous HTTPS instead of SSH
// Remove possible previous HTTPS instead of SSH
yield this . remove GitConfig( this . insteadOfKey , true ) ;
yield this . remove Submodule GitConfig( this . insteadOfKey ) ;
if ( this . settings . persistCredentials ) {
if ( this . settings . persistCredentials ) {
// Configure a placeholder value. This approach avoids the credential being captured
// Get the credentials config file path in RUNNER_TEMP
// by process creation audit events, which are commonly logged. For more information,
const credentialsConfigPath = this . getCredentialsConfigPath ( ) ;
// refer to https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing
// Container credentials config path
const output = yield this . git . submoduleForeach (
const containerCredentialsPath = path . posix . join ( '/github/runner_temp' , path . basename ( credentialsConfigPath ) ) ;
// wrap the pipeline in quotes to make sure it's handled properly by submoduleForeach, rather than just the first part of the pipeline
// Get submodule config file paths.
` sh -c "git config --local ' ${ this . tokenConfigKey } ' ' ${ this . tokenPlaceholderConfigValue } ' && git config --local --show-origin --name-only --get-regexp remote.origin.url" ` , this . settings . nestedSubmodules ) ;
const configPaths = yield this . git . getSubmoduleConfigPaths ( this . settings . nestedSubmodules ) ;
// Replace the placeholder
// For each submodule, configure includeIf entries pointing to the shared credentials file.
const configPaths = output . match ( /(?<=(^|\n)file:)[^\t]+(?=\tremote\.origin\.url)/g ) || [ ] ;
// Configure both host and container paths to support Docker container actions.
for ( const configPath of configPaths ) {
for ( const configPath of configPaths ) {
core . debug ( ` Replacing token placeholder in ' ${ configPath } ' ` ) ;
// Submodule Git directory
yield this . replaceTokenPlaceholder ( configPath ) ;
let submoduleGitDir = path . dirname ( configPath ) ; // The config file is at .git/modules/submodule-name/config
submoduleGitDir = submoduleGitDir . replace ( /\\/g , '/' ) ; // Use forward slashes, even on Windows
// Configure host includeIf
yield this . git . config ( ` includeIf.gitdir: ${ submoduleGitDir } .path ` , credentialsConfigPath , false , // globalConfig?
false , // add?
configPath ) ;
// Container submodule git directory
const githubWorkspace = process . env [ 'GITHUB_WORKSPACE' ] ;
assert . ok ( githubWorkspace , 'GITHUB_WORKSPACE is not defined' ) ;
let relativeSubmoduleGitDir = path . relative ( githubWorkspace , submoduleGitDir ) ;
relativeSubmoduleGitDir = relativeSubmoduleGitDir . replace ( /\\/g , '/' ) ; // Use forward slashes, even on Windows
const containerSubmoduleGitDir = path . posix . join ( '/github/workspace' , relativeSubmoduleGitDir ) ;
// Configure container includeIf
yield this . git . config ( ` includeIf.gitdir: ${ containerSubmoduleGitDir } .path ` , containerCredentialsPath , false , // globalConfig?
false , // add?
configPath ) ;
}
}
if ( this . settings . sshKey ) {
if ( this . settings . sshKey ) {
// Configure core.sshCommand
// Configure core.sshCommand
@ -295,6 +313,10 @@ class GitAuthHelper {
}
}
} ) ;
} ) ;
}
}
/ * *
* Configures SSH authentication by writing the SSH key and known hosts ,
* and setting up the GIT _SSH _COMMAND environment variable .
* /
configureSsh ( ) {
configureSsh ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
if ( ! this . settings . sshKey ) {
if ( ! this . settings . sshKey ) {
@ -351,43 +373,94 @@ class GitAuthHelper {
}
}
} ) ;
} ) ;
}
}
configureToken ( configPath , globalConfig ) {
/ * *
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
* Configures token - based authentication by creating a credentials config file
// Validate args
* and setting up includeIf entries to reference it .
assert . ok ( ( configPath && globalConfig ) || ( ! configPath && ! globalConfig ) , 'Unexpected configureToken parameter combinations' ) ;
* @ param globalConfig Whether to configure global config instead of local
// Default config path
* /
if ( ! configPath && ! globalConfig ) {
configureToken ( globalConfig ) {
configPath = path . join ( this . git . getWorkingDirectory ( ) , '.git' , 'config' ) ;
}
// Configure a placeholder value. This approach avoids the credential being captured
// by process creation audit events, which are commonly logged. For more information,
// refer to https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing
yield this . git . config ( this . tokenConfigKey , this . tokenPlaceholderConfigValue , globalConfig ) ;
// Replace the placeholder
yield this . replaceTokenPlaceholder ( configPath || '' ) ;
} ) ;
}
replaceTokenPlaceholder ( configPath ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
assert . ok ( configPath , 'configPath is not defined' ) ;
// Get the credentials config file path in RUNNER_TEMP
let content = ( yield fs . promises . readFile ( configPath ) ) . toString ( ) ;
const credentialsConfigPath = this . getCredentialsConfigPath ( ) ;
// Write placeholder to the separate credentials config file using git config.
// This approach avoids the credential being captured by process creation audit events,
// which are commonly logged. For more information, refer to
// https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing
yield this . git . config ( this . tokenConfigKey , this . tokenPlaceholderConfigValue , false , // globalConfig?
false , // add?
credentialsConfigPath ) ;
// Replace the placeholder in the credentials config file
let content = ( yield fs . promises . readFile ( credentialsConfigPath ) ) . toString ( ) ;
const placeholderIndex = content . indexOf ( this . tokenPlaceholderConfigValue ) ;
const placeholderIndex = content . indexOf ( this . tokenPlaceholderConfigValue ) ;
if ( placeholderIndex < 0 ||
if ( placeholderIndex < 0 ||
placeholderIndex != content . lastIndexOf ( this . tokenPlaceholderConfigValue ) ) {
placeholderIndex != content . lastIndexOf ( this . tokenPlaceholderConfigValue ) ) {
throw new Error ( ` Unable to replace auth placeholder in ${ configPath } ` ) ;
throw new Error ( ` Unable to replace auth placeholder in ${ c redentialsC onfigPath} ` ) ;
}
}
assert . ok ( this . tokenConfigValue , 'tokenConfigValue is not defined' ) ;
assert . ok ( this . tokenConfigValue , 'tokenConfigValue is not defined' ) ;
content = content . replace ( this . tokenPlaceholderConfigValue , this . tokenConfigValue ) ;
content = content . replace ( this . tokenPlaceholderConfigValue , this . tokenConfigValue ) ;
yield fs . promises . writeFile ( configPath , content ) ;
yield fs . promises . writeFile ( credentialsConfigPath , content ) ;
// Add include or includeIf to reference the credentials config
if ( globalConfig ) {
// Global config file is temporary
yield this . git . config ( 'include.path' , credentialsConfigPath , true // globalConfig?
) ;
}
else {
// Host git directory
let gitDir = path . join ( this . git . getWorkingDirectory ( ) , '.git' ) ;
gitDir = gitDir . replace ( /\\/g , '/' ) ; // Use forward slashes, even on Windows
// Configure host includeIf
const hostIncludeKey = ` includeIf.gitdir: ${ gitDir } .path ` ;
yield this . git . config ( hostIncludeKey , credentialsConfigPath ) ;
// Configure host includeIf for worktrees
const hostWorktreeIncludeKey = ` includeIf.gitdir: ${ gitDir } /worktrees/*.path ` ;
yield this . git . config ( hostWorktreeIncludeKey , credentialsConfigPath ) ;
// Container git directory
const workingDirectory = this . git . getWorkingDirectory ( ) ;
const githubWorkspace = process . env [ 'GITHUB_WORKSPACE' ] ;
assert . ok ( githubWorkspace , 'GITHUB_WORKSPACE is not defined' ) ;
let relativePath = path . relative ( githubWorkspace , workingDirectory ) ;
relativePath = relativePath . replace ( /\\/g , '/' ) ; // Use forward slashes, even on Windows
const containerGitDir = path . posix . join ( '/github/workspace' , relativePath , '.git' ) ;
// Container credentials config path
const containerCredentialsPath = path . posix . join ( '/github/runner_temp' , path . basename ( credentialsConfigPath ) ) ;
// Configure container includeIf
const containerIncludeKey = ` includeIf.gitdir: ${ containerGitDir } .path ` ;
yield this . git . config ( containerIncludeKey , containerCredentialsPath ) ;
// Configure container includeIf for worktrees
const containerWorktreeIncludeKey = ` includeIf.gitdir: ${ containerGitDir } /worktrees/*.path ` ;
yield this . git . config ( containerWorktreeIncludeKey , containerCredentialsPath ) ;
}
} ) ;
} ) ;
}
}
/ * *
* Gets or creates the path to the credentials config file in RUNNER _TEMP .
* @ returns The absolute path to the credentials config file
* /
getCredentialsConfigPath ( ) {
if ( this . credentialsConfigPath ) {
return this . credentialsConfigPath ;
}
const runnerTemp = process . env [ 'RUNNER_TEMP' ] || '' ;
assert . ok ( runnerTemp , 'RUNNER_TEMP is not defined' ) ;
// Create a unique filename for this checkout instance
const configFileName = ` git-credentials- ${ ( 0 , uuid _1 . v4 ) ( ) } .config ` ;
this . credentialsConfigPath = path . join ( runnerTemp , configFileName ) ;
core . debug ( ` Credentials config path: ${ this . credentialsConfigPath } ` ) ;
return this . credentialsConfigPath ;
}
/ * *
* Removes SSH authentication configuration by cleaning up SSH keys ,
* known hosts files , and SSH command configurations .
* /
removeSsh ( ) {
removeSsh ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
var _a ;
var _a , _b ;
// SSH key
// SSH key
const keyPath = this . sshKeyPath || stateHelper . SshKeyPath ;
const keyPath = this . sshKeyPath || stateHelper . SshKeyPath ;
if ( keyPath ) {
if ( keyPath ) {
try {
try {
core . info ( ` Removing SSH key ' ${ keyPath } ' ` ) ;
yield io . rmRF ( keyPath ) ;
yield io . rmRF ( keyPath ) ;
}
}
catch ( err ) {
catch ( err ) {
@ -399,37 +472,136 @@ class GitAuthHelper {
const knownHostsPath = this . sshKnownHostsPath || stateHelper . SshKnownHostsPath ;
const knownHostsPath = this . sshKnownHostsPath || stateHelper . SshKnownHostsPath ;
if ( knownHostsPath ) {
if ( knownHostsPath ) {
try {
try {
core . info ( ` Removing SSH known hosts ' ${ knownHostsPath } ' ` ) ;
yield io . rmRF ( knownHostsPath ) ;
yield io . rmRF ( knownHostsPath ) ;
}
}
catch ( _b ) {
catch ( err ) {
// Intentionally empty
core . debug ( ` ${ ( _b = err === null || err === void 0 ? void 0 : err . message ) !== null && _b !== void 0 ? _b : err } ` ) ;
core . warning ( ` Failed to remove SSH known hosts ' ${ knownHostsPath } ' ` ) ;
}
}
}
}
// SSH command
// SSH command
core . info ( 'Removing SSH command configuration' ) ;
yield this . removeGitConfig ( SSH _COMMAND _KEY ) ;
yield this . removeGitConfig ( SSH _COMMAND _KEY ) ;
yield this . removeSubmoduleGitConfig ( SSH _COMMAND _KEY ) ;
} ) ;
} ) ;
}
}
/ * *
* Removes token - based authentication by cleaning up HTTP headers ,
* includeIf entries , and credentials config files .
* /
removeToken ( ) {
removeToken ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
// HTTP extra header
var _a ;
// Remove HTTP extra header
core . info ( 'Removing HTTP extra header' ) ;
yield this . removeGitConfig ( this . tokenConfigKey ) ;
yield this . removeGitConfig ( this . tokenConfigKey ) ;
yield this . removeSubmoduleGitConfig ( this . tokenConfigKey ) ;
// Collect credentials config paths that need to be removed
const credentialsPaths = new Set ( ) ;
// Remove includeIf entries that point to git-credentials-*.config files
core . info ( 'Removing includeIf entries pointing to credentials config files' ) ;
const mainCredentialsPaths = yield this . removeIncludeIfCredentials ( ) ;
mainCredentialsPaths . forEach ( path => credentialsPaths . add ( path ) ) ;
// Remove submodule includeIf entries that point to git-credentials-*.config files
const submoduleConfigPaths = yield this . git . getSubmoduleConfigPaths ( true ) ;
for ( const configPath of submoduleConfigPaths ) {
const submoduleCredentialsPaths = yield this . removeIncludeIfCredentials ( configPath ) ;
submoduleCredentialsPaths . forEach ( path => credentialsPaths . add ( path ) ) ;
}
// Remove credentials config files
for ( const credentialsPath of credentialsPaths ) {
// Only remove credentials config files if they are under RUNNER_TEMP
const runnerTemp = process . env [ 'RUNNER_TEMP' ] ;
assert . ok ( runnerTemp , 'RUNNER_TEMP is not defined' ) ;
if ( credentialsPath . startsWith ( runnerTemp ) ) {
try {
core . info ( ` Removing credentials config ' ${ credentialsPath } ' ` ) ;
yield io . rmRF ( credentialsPath ) ;
}
catch ( err ) {
core . debug ( ` ${ ( _a = err === null || err === void 0 ? void 0 : err . message ) !== null && _a !== void 0 ? _a : err } ` ) ;
core . warning ( ` Failed to remove credentials config ' ${ credentialsPath } ' ` ) ;
}
}
else {
core . debug ( ` Skipping removal of credentials config ' ${ credentialsPath } ' - not under RUNNER_TEMP ` ) ;
}
}
} ) ;
} ) ;
}
}
removeGitConfig ( configKey _1 ) {
/ * *
return _ _awaiter ( this , arguments , void 0 , function * ( configKey , submoduleOnly = false ) {
* Removes a git config key from the local repository config .
if ( ! submoduleOnly ) {
* @ param configKey The git config key to remove
if ( ( yield this . git . configExists ( configKey ) ) &&
* /
! ( yield this . git . tryConfigUnset ( configKey ) ) ) {
removeGitConfig ( configKey ) {
// Load the config contents
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
core . warning ( ` Failed to remove ' ${ configKey } ' from the git config ` ) ;
if ( ( yield this . git . configExists ( configKey ) ) &&
}
! ( yield this . git . tryConfigUnset ( configKey ) ) ) {
// Load the config contents
core . warning ( ` Failed to remove ' ${ configKey } ' from the git config ` ) ;
}
}
} ) ;
}
/ * *
* Removes a git config key from all submodule configs .
* @ param configKey The git config key to remove
* /
removeSubmoduleGitConfig ( configKey ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
const pattern = regexpHelper . escape ( configKey ) ;
const pattern = regexpHelper . escape ( configKey ) ;
yield this . git . submoduleForeach (
yield this . git . submoduleForeach (
// wrap the pipeline in quotes to make sure it's handled properly by submoduleForeach, rather than just the first part of the pipeline
// W rap the pipeline in quotes to make sure it's handled properly by submoduleForeach, rather than just the first part of the pipeline.
` sh -c "git config --local --name-only --get-regexp ' ${ pattern } ' && git config --local --unset-all ' ${ configKey } ' || :" ` , true ) ;
` sh -c "git config --local --name-only --get-regexp ' ${ pattern } ' && git config --local --unset-all ' ${ configKey } ' || :" ` , true ) ;
} ) ;
} ) ;
}
}
/ * *
* Removes includeIf entries that point to git - credentials - * . config files .
* @ param configPath Optional path to a specific git config file to operate on
* @ returns Array of unique credentials config file paths that were found and removed
* /
removeIncludeIfCredentials ( configPath ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
const credentialsPaths = new Set ( ) ;
try {
// Get all includeIf.gitdir keys
const keys = yield this . git . tryGetConfigKeys ( '^includeIf\\.gitdir:' , false , // globalConfig?
configPath ) ;
for ( const key of keys ) {
// Get all values for this key
const values = yield this . git . tryGetConfigValues ( key , false , // globalConfig?
configPath ) ;
if ( values . length > 0 ) {
// Remove only values that match git-credentials-<uuid>.config pattern
for ( const value of values ) {
if ( this . testCredentialsConfigPath ( value ) ) {
credentialsPaths . add ( value ) ;
yield this . git . tryConfigUnsetValue ( key , value , false , configPath ) ;
}
}
}
}
}
catch ( err ) {
// Ignore errors - this is cleanup code
if ( configPath ) {
core . debug ( ` Error during includeIf cleanup for ${ configPath } : ${ err } ` ) ;
}
else {
core . debug ( ` Error during includeIf cleanup: ${ err } ` ) ;
}
}
return Array . from ( credentialsPaths ) ;
} ) ;
}
/ * *
* Tests if a path matches the git - credentials - * . config pattern .
* @ param path The path to test
* @ returns True if the path matches the credentials config pattern
* /
testCredentialsConfigPath ( path ) {
return /git-credentials-[0-9a-f-]+\.config$/i . test ( path ) ;
}
}
}
@ -627,9 +799,15 @@ class GitCommandManager {
yield this . execGit ( args ) ;
yield this . execGit ( args ) ;
} ) ;
} ) ;
}
}
config ( configKey , configValue , globalConfig , add ) {
config ( configKey , configValue , globalConfig , add , configFile ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
const args = [ 'config' , globalConfig ? '--global' : '--local' ] ;
const args = [ 'config' ] ;
if ( configFile ) {
args . push ( '--file' , configFile ) ;
}
else {
args . push ( globalConfig ? '--global' : '--local' ) ;
}
if ( add ) {
if ( add ) {
args . push ( '--add' ) ;
args . push ( '--add' ) ;
}
}
@ -706,6 +884,16 @@ class GitCommandManager {
throw new Error ( 'Unexpected output when retrieving default branch' ) ;
throw new Error ( 'Unexpected output when retrieving default branch' ) ;
} ) ;
} ) ;
}
}
getSubmoduleConfigPaths ( recursive ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
// Get submodule config file paths.
// Use `--show-origin` to get the config file path for each submodule.
const output = yield this . submoduleForeach ( ` git config --local --show-origin --name-only --get-regexp remote.origin.url ` , recursive ) ;
// Extract config file paths from the output (lines starting with "file:").
const configPaths = output . match ( /(?<=(^|\n)file:)[^\t]+(?=\tremote\.origin\.url)/g ) || [ ] ;
return configPaths ;
} ) ;
}
getWorkingDirectory ( ) {
getWorkingDirectory ( ) {
return this . workingDirectory ;
return this . workingDirectory ;
}
}
@ -836,6 +1024,20 @@ class GitCommandManager {
return output . exitCode === 0 ;
return output . exitCode === 0 ;
} ) ;
} ) ;
}
}
tryConfigUnsetValue ( configKey , configValue , globalConfig , configFile ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
const args = [ 'config' ] ;
if ( configFile ) {
args . push ( '--file' , configFile ) ;
}
else {
args . push ( globalConfig ? '--global' : '--local' ) ;
}
args . push ( '--unset' , configKey , configValue ) ;
const output = yield this . execGit ( args , true ) ;
return output . exitCode === 0 ;
} ) ;
}
tryDisableAutomaticGarbageCollection ( ) {
tryDisableAutomaticGarbageCollection ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
const output = yield this . execGit ( [ 'config' , '--local' , 'gc.auto' , '0' ] , true ) ;
const output = yield this . execGit ( [ 'config' , '--local' , 'gc.auto' , '0' ] , true ) ;
@ -855,6 +1057,46 @@ class GitCommandManager {
return stdout ;
return stdout ;
} ) ;
} ) ;
}
}
tryGetConfigValues ( configKey , globalConfig , configFile ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
const args = [ 'config' ] ;
if ( configFile ) {
args . push ( '--file' , configFile ) ;
}
else {
args . push ( globalConfig ? '--global' : '--local' ) ;
}
args . push ( '--get-all' , configKey ) ;
const output = yield this . execGit ( args , true ) ;
if ( output . exitCode !== 0 ) {
return [ ] ;
}
return output . stdout
. trim ( )
. split ( '\n' )
. filter ( value => value . trim ( ) ) ;
} ) ;
}
tryGetConfigKeys ( pattern , globalConfig , configFile ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
const args = [ 'config' ] ;
if ( configFile ) {
args . push ( '--file' , configFile ) ;
}
else {
args . push ( globalConfig ? '--global' : '--local' ) ;
}
args . push ( '--name-only' , '--get-regexp' , pattern ) ;
const output = yield this . execGit ( args , true ) ;
if ( output . exitCode !== 0 ) {
return [ ] ;
}
return output . stdout
. trim ( )
. split ( '\n' )
. filter ( key => key . trim ( ) ) ;
} ) ;
}
tryReset ( ) {
tryReset ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
const output = yield this . execGit ( [ 'reset' , '--hard' , 'HEAD' ] , true ) ;
const output = yield this . execGit ( [ 'reset' , '--hard' , 'HEAD' ] , true ) ;