diff options
| author | eric sciple <ericsciple@users.noreply.github.com> | 2020-03-02 11:33:30 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-03-02 11:33:30 -0500 |
| commit | 684bbf983233d1341d533f6fe471109f385c631a (patch) | |
| tree | b1b1ad193814c44cf1e7b450c00c005ed96c0a6d /src/git-source-provider.ts | |
| parent | dee20e9b25075b7e4d2fc1569a2e99e21905e978 (diff) | |
more unit tests and corresponding refactoring (#174)
Diffstat (limited to 'src/git-source-provider.ts')
| -rw-r--r-- | src/git-source-provider.ts | 185 |
1 files changed, 20 insertions, 165 deletions
diff --git a/src/git-source-provider.ts b/src/git-source-provider.ts index e0dd58e..34b822c 100644 --- a/src/git-source-provider.ts +++ b/src/git-source-provider.ts @@ -1,36 +1,24 @@ import * as core from '@actions/core' -import * as fs from 'fs' import * as fsHelper from './fs-helper' +import * as gitAuthHelper from './git-auth-helper' import * as gitCommandManager from './git-command-manager' +import * as gitDirectoryHelper from './git-directory-helper' import * as githubApiHelper from './github-api-helper' import * as io from '@actions/io' import * as path from 'path' import * as refHelper from './ref-helper' import * as stateHelper from './state-helper' import {IGitCommandManager} from './git-command-manager' +import {IGitSourceSettings} from './git-source-settings' -const serverUrl = 'https://github.com/' -const authConfigKey = `http.${serverUrl}.extraheader` +const hostname = 'github.com' -export interface ISourceSettings { - repositoryPath: string - repositoryOwner: string - repositoryName: string - ref: string - commit: string - clean: boolean - fetchDepth: number - lfs: boolean - authToken: string - persistCredentials: boolean -} - -export async function getSource(settings: ISourceSettings): Promise<void> { +export async function getSource(settings: IGitSourceSettings): Promise<void> { // Repository URL core.info( `Syncing repository: ${settings.repositoryOwner}/${settings.repositoryName}` ) - const repositoryUrl = `https://github.com/${encodeURIComponent( + const repositoryUrl = `https://${hostname}/${encodeURIComponent( settings.repositoryOwner )}/${encodeURIComponent(settings.repositoryName)}` @@ -51,7 +39,7 @@ export async function getSource(settings: ISourceSettings): Promise<void> { // Prepare existing directory, otherwise recreate if (isExisting) { - await prepareExistingDirectory( + await gitDirectoryHelper.prepareExistingDirectory( git, settings.repositoryPath, repositoryUrl, @@ -92,12 +80,10 @@ export async function getSource(settings: ISourceSettings): Promise<void> { ) } - // Remove possible previous extraheader - await removeGitConfig(git, authConfigKey) - + const authHelper = gitAuthHelper.createAuthHelper(git, settings) try { - // Config extraheader - await configureAuthToken(git, settings.authToken) + // Configure auth + await authHelper.configureAuth() // LFS install if (settings.lfs) { @@ -128,8 +114,9 @@ export async function getSource(settings: ISourceSettings): Promise<void> { // Dump some info about the checked out commit await git.log1() } finally { + // Remove auth if (!settings.persistCredentials) { - await removeGitConfig(git, authConfigKey) + await authHelper.removeAuth() } } } @@ -146,22 +133,22 @@ export async function cleanup(repositoryPath: string): Promise<void> { let git: IGitCommandManager try { - git = await gitCommandManager.CreateCommandManager(repositoryPath, false) + git = await gitCommandManager.createCommandManager(repositoryPath, false) } catch { return } - // Remove extraheader - await removeGitConfig(git, authConfigKey) + // Remove auth + const authHelper = gitAuthHelper.createAuthHelper(git) + await authHelper.removeAuth() } async function getGitCommandManager( - settings: ISourceSettings -): Promise<IGitCommandManager> { + settings: IGitSourceSettings +): Promise<IGitCommandManager | undefined> { core.info(`Working directory is '${settings.repositoryPath}'`) - let git = (null as unknown) as IGitCommandManager try { - return await gitCommandManager.CreateCommandManager( + return await gitCommandManager.createCommandManager( settings.repositoryPath, settings.lfs ) @@ -172,138 +159,6 @@ async function getGitCommandManager( } // Otherwise fallback to REST API - return (null as unknown) as IGitCommandManager - } -} - -async function prepareExistingDirectory( - git: IGitCommandManager, - repositoryPath: string, - repositoryUrl: string, - clean: boolean -): Promise<void> { - let remove = false - - // Check whether using git or REST API - if (!git) { - remove = true - } - // Fetch URL does not match - else if ( - !fsHelper.directoryExistsSync(path.join(repositoryPath, '.git')) || - repositoryUrl !== (await git.tryGetFetchUrl()) - ) { - remove = true - } else { - // Delete any index.lock and shallow.lock left by a previously canceled run or crashed git process - const lockPaths = [ - path.join(repositoryPath, '.git', 'index.lock'), - path.join(repositoryPath, '.git', 'shallow.lock') - ] - for (const lockPath of lockPaths) { - try { - await io.rmRF(lockPath) - } catch (error) { - core.debug(`Unable to delete '${lockPath}'. ${error.message}`) - } - } - - try { - // Checkout detached HEAD - if (!(await git.isDetached())) { - await git.checkoutDetach() - } - - // Remove all refs/heads/* - let branches = await git.branchList(false) - for (const branch of branches) { - await git.branchDelete(false, branch) - } - - // Remove all refs/remotes/origin/* to avoid conflicts - branches = await git.branchList(true) - for (const branch of branches) { - await git.branchDelete(true, branch) - } - - // Clean - if (clean) { - if (!(await git.tryClean())) { - core.debug( - `The clean command failed. This might be caused by: 1) path too long, 2) permission issue, or 3) file in use. For futher investigation, manually run 'git clean -ffdx' on the directory '${repositoryPath}'.` - ) - remove = true - } else if (!(await git.tryReset())) { - remove = true - } - - if (remove) { - core.warning( - `Unable to clean or reset the repository. The repository will be recreated instead.` - ) - } - } - } catch (error) { - core.warning( - `Unable to prepare the existing repository. The repository will be recreated instead.` - ) - remove = true - } - } - - if (remove) { - // Delete the contents of the directory. Don't delete the directory itself - // since it might be the current working directory. - core.info(`Deleting the contents of '${repositoryPath}'`) - for (const file of await fs.promises.readdir(repositoryPath)) { - await io.rmRF(path.join(repositoryPath, file)) - } - } -} - -async function configureAuthToken( - git: IGitCommandManager, - authToken: string -): Promise<void> { - // 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 - const placeholder = `AUTHORIZATION: basic ***` - await git.config(authConfigKey, placeholder) - - // Determine the basic credential value - const basicCredential = Buffer.from( - `x-access-token:${authToken}`, - 'utf8' - ).toString('base64') - core.setSecret(basicCredential) - - // Replace the value in the config file - const configPath = path.join(git.getWorkingDirectory(), '.git', 'config') - let content = (await fs.promises.readFile(configPath)).toString() - const placeholderIndex = content.indexOf(placeholder) - if ( - placeholderIndex < 0 || - placeholderIndex != content.lastIndexOf(placeholder) - ) { - throw new Error('Unable to replace auth placeholder in .git/config') - } - content = content.replace( - placeholder, - `AUTHORIZATION: basic ${basicCredential}` - ) - await fs.promises.writeFile(configPath, content) -} - -async function removeGitConfig( - git: IGitCommandManager, - configKey: string -): Promise<void> { - if ( - (await git.configExists(configKey)) && - !(await git.tryConfigUnset(configKey)) - ) { - // Load the config contents - core.warning(`Failed to remove '${configKey}' from the git config`) + return undefined } } |
