mirror of
				https://github.com/actions/checkout.git
				synced 2025-10-31 10:08:37 +08:00 
			
		
		
		
	Delete __test__ directory
This commit is contained in:
		
							parent
							
								
									00c37740b7
								
							
						
					
					
						commit
						f0aad2b562
					
				|  | @ -1,856 +0,0 @@ | ||||||
| import * as core from '@actions/core' |  | ||||||
| import * as fs from 'fs' |  | ||||||
| import * as gitAuthHelper from '../lib/git-auth-helper' |  | ||||||
| import * as io from '@actions/io' |  | ||||||
| import * as os from 'os' |  | ||||||
| import * as path from 'path' |  | ||||||
| import * as stateHelper from '../lib/state-helper' |  | ||||||
| import {IGitCommandManager} from '../lib/git-command-manager' |  | ||||||
| import {IGitSourceSettings} from '../lib/git-source-settings' |  | ||||||
| 
 |  | ||||||
| const isWindows = process.platform === 'win32' |  | ||||||
| const testWorkspace = path.join(__dirname, '_temp', 'git-auth-helper') |  | ||||||
| const originalRunnerTemp = process.env['RUNNER_TEMP'] |  | ||||||
| const originalHome = process.env['HOME'] |  | ||||||
| let workspace: string |  | ||||||
| let localGitConfigPath: string |  | ||||||
| let globalGitConfigPath: string |  | ||||||
| let runnerTemp: string |  | ||||||
| let tempHomedir: string |  | ||||||
| let git: IGitCommandManager & {env: {[key: string]: string}} |  | ||||||
| let settings: IGitSourceSettings |  | ||||||
| let sshPath: string |  | ||||||
| let githubServerUrl: string |  | ||||||
| 
 |  | ||||||
| describe('git-auth-helper tests', () => { |  | ||||||
|   beforeAll(async () => { |  | ||||||
|     // SSH
 |  | ||||||
|     sshPath = await io.which('ssh') |  | ||||||
| 
 |  | ||||||
|     // Clear test workspace
 |  | ||||||
|     await io.rmRF(testWorkspace) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   beforeEach(() => { |  | ||||||
|     // Mock setSecret
 |  | ||||||
|     jest.spyOn(core, 'setSecret').mockImplementation((secret: string) => {}) |  | ||||||
| 
 |  | ||||||
|     // Mock error/warning/info/debug
 |  | ||||||
|     jest.spyOn(core, 'error').mockImplementation(jest.fn()) |  | ||||||
|     jest.spyOn(core, 'warning').mockImplementation(jest.fn()) |  | ||||||
|     jest.spyOn(core, 'info').mockImplementation(jest.fn()) |  | ||||||
|     jest.spyOn(core, 'debug').mockImplementation(jest.fn()) |  | ||||||
| 
 |  | ||||||
|     // Mock state helper
 |  | ||||||
|     jest.spyOn(stateHelper, 'setSshKeyPath').mockImplementation(jest.fn()) |  | ||||||
|     jest |  | ||||||
|       .spyOn(stateHelper, 'setSshKnownHostsPath') |  | ||||||
|       .mockImplementation(jest.fn()) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   afterEach(() => { |  | ||||||
|     // Unregister mocks
 |  | ||||||
|     jest.restoreAllMocks() |  | ||||||
| 
 |  | ||||||
|     // Restore HOME
 |  | ||||||
|     if (originalHome) { |  | ||||||
|       process.env['HOME'] = originalHome |  | ||||||
|     } else { |  | ||||||
|       delete process.env['HOME'] |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   afterAll(() => { |  | ||||||
|     // Restore RUNNER_TEMP
 |  | ||||||
|     delete process.env['RUNNER_TEMP'] |  | ||||||
|     if (originalRunnerTemp) { |  | ||||||
|       process.env['RUNNER_TEMP'] = originalRunnerTemp |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   async function testAuthHeader( |  | ||||||
|     testName: string, |  | ||||||
|     serverUrl: string | undefined = undefined |  | ||||||
|   ) { |  | ||||||
|     // Arrange
 |  | ||||||
|     let expectedServerUrl = 'https://github.com' |  | ||||||
|     if (serverUrl) { |  | ||||||
|       githubServerUrl = serverUrl |  | ||||||
|       expectedServerUrl = githubServerUrl |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     await setup(testName) |  | ||||||
|     expect(settings.authToken).toBeTruthy() // sanity check
 |  | ||||||
|     const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await authHelper.configureAuth() |  | ||||||
| 
 |  | ||||||
|     // Assert config
 |  | ||||||
|     const configContent = ( |  | ||||||
|       await fs.promises.readFile(localGitConfigPath) |  | ||||||
|     ).toString() |  | ||||||
|     const basicCredential = Buffer.from( |  | ||||||
|       `x-access-token:${settings.authToken}`, |  | ||||||
|       'utf8' |  | ||||||
|     ).toString('base64') |  | ||||||
|     expect( |  | ||||||
|       configContent.indexOf( |  | ||||||
|         `http.${expectedServerUrl}/.extraheader AUTHORIZATION: basic ${basicCredential}` |  | ||||||
|       ) |  | ||||||
|     ).toBeGreaterThanOrEqual(0) |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   const configureAuth_configuresAuthHeader = |  | ||||||
|     'configureAuth configures auth header' |  | ||||||
|   it(configureAuth_configuresAuthHeader, async () => { |  | ||||||
|     await testAuthHeader(configureAuth_configuresAuthHeader) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const configureAuth_AcceptsGitHubServerUrl = |  | ||||||
|     'inject https://my-ghes-server.com as github server url' |  | ||||||
|   it(configureAuth_AcceptsGitHubServerUrl, async () => { |  | ||||||
|     await testAuthHeader( |  | ||||||
|       configureAuth_AcceptsGitHubServerUrl, |  | ||||||
|       'https://my-ghes-server.com' |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const configureAuth_AcceptsGitHubServerUrlSetToGHEC = |  | ||||||
|     'inject https://github.com as github server url' |  | ||||||
|   it(configureAuth_AcceptsGitHubServerUrlSetToGHEC, async () => { |  | ||||||
|     await testAuthHeader( |  | ||||||
|       configureAuth_AcceptsGitHubServerUrl, |  | ||||||
|       'https://github.com' |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const configureAuth_configuresAuthHeaderEvenWhenPersistCredentialsFalse = |  | ||||||
|     'configureAuth configures auth header even when persist credentials false' |  | ||||||
|   it( |  | ||||||
|     configureAuth_configuresAuthHeaderEvenWhenPersistCredentialsFalse, |  | ||||||
|     async () => { |  | ||||||
|       // Arrange
 |  | ||||||
|       await setup( |  | ||||||
|         configureAuth_configuresAuthHeaderEvenWhenPersistCredentialsFalse |  | ||||||
|       ) |  | ||||||
|       expect(settings.authToken).toBeTruthy() // sanity check
 |  | ||||||
|       settings.persistCredentials = false |  | ||||||
|       const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
| 
 |  | ||||||
|       // Act
 |  | ||||||
|       await authHelper.configureAuth() |  | ||||||
| 
 |  | ||||||
|       // Assert config
 |  | ||||||
|       const configContent = ( |  | ||||||
|         await fs.promises.readFile(localGitConfigPath) |  | ||||||
|       ).toString() |  | ||||||
|       expect( |  | ||||||
|         configContent.indexOf( |  | ||||||
|           `http.https://github.com/.extraheader AUTHORIZATION` |  | ||||||
|         ) |  | ||||||
|       ).toBeGreaterThanOrEqual(0) |  | ||||||
|     } |  | ||||||
|   ) |  | ||||||
| 
 |  | ||||||
|   const configureAuth_copiesUserKnownHosts = |  | ||||||
|     'configureAuth copies user known hosts' |  | ||||||
|   it(configureAuth_copiesUserKnownHosts, async () => { |  | ||||||
|     if (!sshPath) { |  | ||||||
|       process.stdout.write( |  | ||||||
|         `Skipped test "${configureAuth_copiesUserKnownHosts}". Executable 'ssh' not found in the PATH.\n` |  | ||||||
|       ) |  | ||||||
|       return |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Arange
 |  | ||||||
|     await setup(configureAuth_copiesUserKnownHosts) |  | ||||||
|     expect(settings.sshKey).toBeTruthy() // sanity check
 |  | ||||||
| 
 |  | ||||||
|     // Mock fs.promises.readFile
 |  | ||||||
|     const realReadFile = fs.promises.readFile |  | ||||||
|     jest |  | ||||||
|       .spyOn(fs.promises, 'readFile') |  | ||||||
|       .mockImplementation(async (file: any, options: any): Promise<Buffer> => { |  | ||||||
|         const userKnownHostsPath = path.join( |  | ||||||
|           os.homedir(), |  | ||||||
|           '.ssh', |  | ||||||
|           'known_hosts' |  | ||||||
|         ) |  | ||||||
|         if (file === userKnownHostsPath) { |  | ||||||
|           return Buffer.from('some-domain.com ssh-rsa ABCDEF') |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return await realReadFile(file, options) |  | ||||||
|       }) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
|     await authHelper.configureAuth() |  | ||||||
| 
 |  | ||||||
|     // Assert known hosts
 |  | ||||||
|     const actualSshKnownHostsPath = await getActualSshKnownHostsPath() |  | ||||||
|     const actualSshKnownHostsContent = ( |  | ||||||
|       await fs.promises.readFile(actualSshKnownHostsPath) |  | ||||||
|     ).toString() |  | ||||||
|     expect(actualSshKnownHostsContent).toMatch( |  | ||||||
|       /some-domain\.com ssh-rsa ABCDEF/ |  | ||||||
|     ) |  | ||||||
|     expect(actualSshKnownHostsContent).toMatch(/github\.com ssh-rsa AAAAB3N/) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const configureAuth_registersBasicCredentialAsSecret = |  | ||||||
|     'configureAuth registers basic credential as secret' |  | ||||||
|   it(configureAuth_registersBasicCredentialAsSecret, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(configureAuth_registersBasicCredentialAsSecret) |  | ||||||
|     expect(settings.authToken).toBeTruthy() // sanity check
 |  | ||||||
|     const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await authHelper.configureAuth() |  | ||||||
| 
 |  | ||||||
|     // Assert secret
 |  | ||||||
|     const setSecretSpy = core.setSecret as jest.Mock<any, any> |  | ||||||
|     expect(setSecretSpy).toHaveBeenCalledTimes(1) |  | ||||||
|     const expectedSecret = Buffer.from( |  | ||||||
|       `x-access-token:${settings.authToken}`, |  | ||||||
|       'utf8' |  | ||||||
|     ).toString('base64') |  | ||||||
|     expect(setSecretSpy).toHaveBeenCalledWith(expectedSecret) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const setsSshCommandEnvVarWhenPersistCredentialsFalse = |  | ||||||
|     'sets SSH command env var when persist-credentials false' |  | ||||||
|   it(setsSshCommandEnvVarWhenPersistCredentialsFalse, async () => { |  | ||||||
|     if (!sshPath) { |  | ||||||
|       process.stdout.write( |  | ||||||
|         `Skipped test "${setsSshCommandEnvVarWhenPersistCredentialsFalse}". Executable 'ssh' not found in the PATH.\n` |  | ||||||
|       ) |  | ||||||
|       return |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(setsSshCommandEnvVarWhenPersistCredentialsFalse) |  | ||||||
|     settings.persistCredentials = false |  | ||||||
|     const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await authHelper.configureAuth() |  | ||||||
| 
 |  | ||||||
|     // Assert git env var
 |  | ||||||
|     const actualKeyPath = await getActualSshKeyPath() |  | ||||||
|     const actualKnownHostsPath = await getActualSshKnownHostsPath() |  | ||||||
|     const expectedSshCommand = `"${sshPath}" -i "$RUNNER_TEMP/${path.basename( |  | ||||||
|       actualKeyPath |  | ||||||
|     )}" -o StrictHostKeyChecking=yes -o CheckHostIP=no -o "UserKnownHostsFile=$RUNNER_TEMP/${path.basename( |  | ||||||
|       actualKnownHostsPath |  | ||||||
|     )}"` |  | ||||||
|     expect(git.setEnvironmentVariable).toHaveBeenCalledWith( |  | ||||||
|       'GIT_SSH_COMMAND', |  | ||||||
|       expectedSshCommand |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Asserty git config
 |  | ||||||
|     const gitConfigLines = (await fs.promises.readFile(localGitConfigPath)) |  | ||||||
|       .toString() |  | ||||||
|       .split('\n') |  | ||||||
|       .filter(x => x) |  | ||||||
|     expect(gitConfigLines).toHaveLength(1) |  | ||||||
|     expect(gitConfigLines[0]).toMatch(/^http\./) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const configureAuth_setsSshCommandWhenPersistCredentialsTrue = |  | ||||||
|     'sets SSH command when persist-credentials true' |  | ||||||
|   it(configureAuth_setsSshCommandWhenPersistCredentialsTrue, async () => { |  | ||||||
|     if (!sshPath) { |  | ||||||
|       process.stdout.write( |  | ||||||
|         `Skipped test "${configureAuth_setsSshCommandWhenPersistCredentialsTrue}". Executable 'ssh' not found in the PATH.\n` |  | ||||||
|       ) |  | ||||||
|       return |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(configureAuth_setsSshCommandWhenPersistCredentialsTrue) |  | ||||||
|     const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await authHelper.configureAuth() |  | ||||||
| 
 |  | ||||||
|     // Assert git env var
 |  | ||||||
|     const actualKeyPath = await getActualSshKeyPath() |  | ||||||
|     const actualKnownHostsPath = await getActualSshKnownHostsPath() |  | ||||||
|     const expectedSshCommand = `"${sshPath}" -i "$RUNNER_TEMP/${path.basename( |  | ||||||
|       actualKeyPath |  | ||||||
|     )}" -o StrictHostKeyChecking=yes -o CheckHostIP=no -o "UserKnownHostsFile=$RUNNER_TEMP/${path.basename( |  | ||||||
|       actualKnownHostsPath |  | ||||||
|     )}"` |  | ||||||
|     expect(git.setEnvironmentVariable).toHaveBeenCalledWith( |  | ||||||
|       'GIT_SSH_COMMAND', |  | ||||||
|       expectedSshCommand |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Asserty git config
 |  | ||||||
|     expect(git.config).toHaveBeenCalledWith( |  | ||||||
|       'core.sshCommand', |  | ||||||
|       expectedSshCommand |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const configureAuth_writesExplicitKnownHosts = 'writes explicit known hosts' |  | ||||||
|   it(configureAuth_writesExplicitKnownHosts, async () => { |  | ||||||
|     if (!sshPath) { |  | ||||||
|       process.stdout.write( |  | ||||||
|         `Skipped test "${configureAuth_writesExplicitKnownHosts}". Executable 'ssh' not found in the PATH.\n` |  | ||||||
|       ) |  | ||||||
|       return |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(configureAuth_writesExplicitKnownHosts) |  | ||||||
|     expect(settings.sshKey).toBeTruthy() // sanity check
 |  | ||||||
|     settings.sshKnownHosts = 'my-custom-host.com ssh-rsa ABC123' |  | ||||||
|     const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await authHelper.configureAuth() |  | ||||||
| 
 |  | ||||||
|     // Assert known hosts
 |  | ||||||
|     const actualSshKnownHostsPath = await getActualSshKnownHostsPath() |  | ||||||
|     const actualSshKnownHostsContent = ( |  | ||||||
|       await fs.promises.readFile(actualSshKnownHostsPath) |  | ||||||
|     ).toString() |  | ||||||
|     expect(actualSshKnownHostsContent).toMatch( |  | ||||||
|       /my-custom-host\.com ssh-rsa ABC123/ |  | ||||||
|     ) |  | ||||||
|     expect(actualSshKnownHostsContent).toMatch(/github\.com ssh-rsa AAAAB3N/) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const configureAuth_writesSshKeyAndImplicitKnownHosts = |  | ||||||
|     'writes SSH key and implicit known hosts' |  | ||||||
|   it(configureAuth_writesSshKeyAndImplicitKnownHosts, async () => { |  | ||||||
|     if (!sshPath) { |  | ||||||
|       process.stdout.write( |  | ||||||
|         `Skipped test "${configureAuth_writesSshKeyAndImplicitKnownHosts}". Executable 'ssh' not found in the PATH.\n` |  | ||||||
|       ) |  | ||||||
|       return |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(configureAuth_writesSshKeyAndImplicitKnownHosts) |  | ||||||
|     expect(settings.sshKey).toBeTruthy() // sanity check
 |  | ||||||
|     const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await authHelper.configureAuth() |  | ||||||
| 
 |  | ||||||
|     // Assert SSH key
 |  | ||||||
|     const actualSshKeyPath = await getActualSshKeyPath() |  | ||||||
|     expect(actualSshKeyPath).toBeTruthy() |  | ||||||
|     const actualSshKeyContent = ( |  | ||||||
|       await fs.promises.readFile(actualSshKeyPath) |  | ||||||
|     ).toString() |  | ||||||
|     expect(actualSshKeyContent).toBe(settings.sshKey + '\n') |  | ||||||
|     if (!isWindows) { |  | ||||||
|       // Assert read/write for user, not group or others.
 |  | ||||||
|       // Otherwise SSH client will error.
 |  | ||||||
|       expect((await fs.promises.stat(actualSshKeyPath)).mode & 0o777).toBe( |  | ||||||
|         0o600 |  | ||||||
|       ) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Assert known hosts
 |  | ||||||
|     const actualSshKnownHostsPath = await getActualSshKnownHostsPath() |  | ||||||
|     const actualSshKnownHostsContent = ( |  | ||||||
|       await fs.promises.readFile(actualSshKnownHostsPath) |  | ||||||
|     ).toString() |  | ||||||
|     expect(actualSshKnownHostsContent).toMatch(/github\.com ssh-rsa AAAAB3N/) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const configureGlobalAuth_configuresUrlInsteadOfWhenSshKeyNotSet = |  | ||||||
|     'configureGlobalAuth configures URL insteadOf when SSH key not set' |  | ||||||
|   it(configureGlobalAuth_configuresUrlInsteadOfWhenSshKeyNotSet, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(configureGlobalAuth_configuresUrlInsteadOfWhenSshKeyNotSet) |  | ||||||
|     settings.sshKey = '' |  | ||||||
|     const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await authHelper.configureAuth() |  | ||||||
|     await authHelper.configureGlobalAuth() |  | ||||||
| 
 |  | ||||||
|     // Assert temporary global config
 |  | ||||||
|     expect(git.env['HOME']).toBeTruthy() |  | ||||||
|     const configContent = ( |  | ||||||
|       await fs.promises.readFile(path.join(git.env['HOME'], '.gitconfig')) |  | ||||||
|     ).toString() |  | ||||||
|     expect( |  | ||||||
|       configContent.indexOf(`url.https://github.com/.insteadOf git@github.com`) |  | ||||||
|     ).toBeGreaterThanOrEqual(0) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const configureGlobalAuth_copiesGlobalGitConfig = |  | ||||||
|     'configureGlobalAuth copies global git config' |  | ||||||
|   it(configureGlobalAuth_copiesGlobalGitConfig, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(configureGlobalAuth_copiesGlobalGitConfig) |  | ||||||
|     await fs.promises.writeFile(globalGitConfigPath, 'value-from-global-config') |  | ||||||
|     const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await authHelper.configureAuth() |  | ||||||
|     await authHelper.configureGlobalAuth() |  | ||||||
| 
 |  | ||||||
|     // Assert original global config not altered
 |  | ||||||
|     let configContent = ( |  | ||||||
|       await fs.promises.readFile(globalGitConfigPath) |  | ||||||
|     ).toString() |  | ||||||
|     expect(configContent).toBe('value-from-global-config') |  | ||||||
| 
 |  | ||||||
|     // Assert temporary global config
 |  | ||||||
|     expect(git.env['HOME']).toBeTruthy() |  | ||||||
|     const basicCredential = Buffer.from( |  | ||||||
|       `x-access-token:${settings.authToken}`, |  | ||||||
|       'utf8' |  | ||||||
|     ).toString('base64') |  | ||||||
|     configContent = ( |  | ||||||
|       await fs.promises.readFile(path.join(git.env['HOME'], '.gitconfig')) |  | ||||||
|     ).toString() |  | ||||||
|     expect( |  | ||||||
|       configContent.indexOf('value-from-global-config') |  | ||||||
|     ).toBeGreaterThanOrEqual(0) |  | ||||||
|     expect( |  | ||||||
|       configContent.indexOf( |  | ||||||
|         `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}` |  | ||||||
|       ) |  | ||||||
|     ).toBeGreaterThanOrEqual(0) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist = |  | ||||||
|     'configureGlobalAuth creates new git config when global does not exist' |  | ||||||
|   it( |  | ||||||
|     configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist, |  | ||||||
|     async () => { |  | ||||||
|       // Arrange
 |  | ||||||
|       await setup( |  | ||||||
|         configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist |  | ||||||
|       ) |  | ||||||
|       await io.rmRF(globalGitConfigPath) |  | ||||||
|       const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
| 
 |  | ||||||
|       // Act
 |  | ||||||
|       await authHelper.configureAuth() |  | ||||||
|       await authHelper.configureGlobalAuth() |  | ||||||
| 
 |  | ||||||
|       // Assert original global config not recreated
 |  | ||||||
|       try { |  | ||||||
|         await fs.promises.stat(globalGitConfigPath) |  | ||||||
|         throw new Error( |  | ||||||
|           `Did not expect file to exist: '${globalGitConfigPath}'` |  | ||||||
|         ) |  | ||||||
|       } catch (err) { |  | ||||||
|         if ((err as any)?.code !== 'ENOENT') { |  | ||||||
|           throw err |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       // Assert temporary global config
 |  | ||||||
|       expect(git.env['HOME']).toBeTruthy() |  | ||||||
|       const basicCredential = Buffer.from( |  | ||||||
|         `x-access-token:${settings.authToken}`, |  | ||||||
|         'utf8' |  | ||||||
|       ).toString('base64') |  | ||||||
|       const configContent = ( |  | ||||||
|         await fs.promises.readFile(path.join(git.env['HOME'], '.gitconfig')) |  | ||||||
|       ).toString() |  | ||||||
|       expect( |  | ||||||
|         configContent.indexOf( |  | ||||||
|           `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}` |  | ||||||
|         ) |  | ||||||
|       ).toBeGreaterThanOrEqual(0) |  | ||||||
|     } |  | ||||||
|   ) |  | ||||||
| 
 |  | ||||||
|   const configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeyNotSet = |  | ||||||
|     'configureSubmoduleAuth configures submodules when persist credentials false and SSH key not set' |  | ||||||
|   it( |  | ||||||
|     configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeyNotSet, |  | ||||||
|     async () => { |  | ||||||
|       // Arrange
 |  | ||||||
|       await setup( |  | ||||||
|         configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeyNotSet |  | ||||||
|       ) |  | ||||||
|       settings.persistCredentials = false |  | ||||||
|       settings.sshKey = '' |  | ||||||
|       const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
|       await authHelper.configureAuth() |  | ||||||
|       const mockSubmoduleForeach = git.submoduleForeach as jest.Mock<any, any> |  | ||||||
|       mockSubmoduleForeach.mockClear() // reset calls
 |  | ||||||
| 
 |  | ||||||
|       // Act
 |  | ||||||
|       await authHelper.configureSubmoduleAuth() |  | ||||||
| 
 |  | ||||||
|       // Assert
 |  | ||||||
|       expect(mockSubmoduleForeach).toBeCalledTimes(1) |  | ||||||
|       expect(mockSubmoduleForeach.mock.calls[0][0] as string).toMatch( |  | ||||||
|         /unset-all.*insteadOf/ |  | ||||||
|       ) |  | ||||||
|     } |  | ||||||
|   ) |  | ||||||
| 
 |  | ||||||
|   const configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeySet = |  | ||||||
|     'configureSubmoduleAuth configures submodules when persist credentials false and SSH key set' |  | ||||||
|   it( |  | ||||||
|     configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeySet, |  | ||||||
|     async () => { |  | ||||||
|       if (!sshPath) { |  | ||||||
|         process.stdout.write( |  | ||||||
|           `Skipped test "${configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeySet}". Executable 'ssh' not found in the PATH.\n` |  | ||||||
|         ) |  | ||||||
|         return |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       // Arrange
 |  | ||||||
|       await setup( |  | ||||||
|         configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeySet |  | ||||||
|       ) |  | ||||||
|       settings.persistCredentials = false |  | ||||||
|       const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
|       await authHelper.configureAuth() |  | ||||||
|       const mockSubmoduleForeach = git.submoduleForeach as jest.Mock<any, any> |  | ||||||
|       mockSubmoduleForeach.mockClear() // reset calls
 |  | ||||||
| 
 |  | ||||||
|       // Act
 |  | ||||||
|       await authHelper.configureSubmoduleAuth() |  | ||||||
| 
 |  | ||||||
|       // Assert
 |  | ||||||
|       expect(mockSubmoduleForeach).toHaveBeenCalledTimes(1) |  | ||||||
|       expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch( |  | ||||||
|         /unset-all.*insteadOf/ |  | ||||||
|       ) |  | ||||||
|     } |  | ||||||
|   ) |  | ||||||
| 
 |  | ||||||
|   const configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeyNotSet = |  | ||||||
|     'configureSubmoduleAuth configures submodules when persist credentials true and SSH key not set' |  | ||||||
|   it( |  | ||||||
|     configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeyNotSet, |  | ||||||
|     async () => { |  | ||||||
|       // Arrange
 |  | ||||||
|       await setup( |  | ||||||
|         configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeyNotSet |  | ||||||
|       ) |  | ||||||
|       settings.sshKey = '' |  | ||||||
|       const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
|       await authHelper.configureAuth() |  | ||||||
|       const mockSubmoduleForeach = git.submoduleForeach as jest.Mock<any, any> |  | ||||||
|       mockSubmoduleForeach.mockClear() // reset calls
 |  | ||||||
| 
 |  | ||||||
|       // Act
 |  | ||||||
|       await authHelper.configureSubmoduleAuth() |  | ||||||
| 
 |  | ||||||
|       // Assert
 |  | ||||||
|       expect(mockSubmoduleForeach).toHaveBeenCalledTimes(4) |  | ||||||
|       expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch( |  | ||||||
|         /unset-all.*insteadOf/ |  | ||||||
|       ) |  | ||||||
|       expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/) |  | ||||||
|       expect(mockSubmoduleForeach.mock.calls[2][0]).toMatch( |  | ||||||
|         /url.*insteadOf.*git@github.com:/ |  | ||||||
|       ) |  | ||||||
|       expect(mockSubmoduleForeach.mock.calls[3][0]).toMatch( |  | ||||||
|         /url.*insteadOf.*org-123456@github.com:/ |  | ||||||
|       ) |  | ||||||
|     } |  | ||||||
|   ) |  | ||||||
| 
 |  | ||||||
|   const configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeySet = |  | ||||||
|     'configureSubmoduleAuth configures submodules when persist credentials true and SSH key set' |  | ||||||
|   it( |  | ||||||
|     configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeySet, |  | ||||||
|     async () => { |  | ||||||
|       if (!sshPath) { |  | ||||||
|         process.stdout.write( |  | ||||||
|           `Skipped test "${configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeySet}". Executable 'ssh' not found in the PATH.\n` |  | ||||||
|         ) |  | ||||||
|         return |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       // Arrange
 |  | ||||||
|       await setup( |  | ||||||
|         configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeySet |  | ||||||
|       ) |  | ||||||
|       const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
|       await authHelper.configureAuth() |  | ||||||
|       const mockSubmoduleForeach = git.submoduleForeach as jest.Mock<any, any> |  | ||||||
|       mockSubmoduleForeach.mockClear() // reset calls
 |  | ||||||
| 
 |  | ||||||
|       // Act
 |  | ||||||
|       await authHelper.configureSubmoduleAuth() |  | ||||||
| 
 |  | ||||||
|       // Assert
 |  | ||||||
|       expect(mockSubmoduleForeach).toHaveBeenCalledTimes(3) |  | ||||||
|       expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch( |  | ||||||
|         /unset-all.*insteadOf/ |  | ||||||
|       ) |  | ||||||
|       expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/) |  | ||||||
|       expect(mockSubmoduleForeach.mock.calls[2][0]).toMatch(/core\.sshCommand/) |  | ||||||
|     } |  | ||||||
|   ) |  | ||||||
| 
 |  | ||||||
|   const removeAuth_removesSshCommand = 'removeAuth removes SSH command' |  | ||||||
|   it(removeAuth_removesSshCommand, async () => { |  | ||||||
|     if (!sshPath) { |  | ||||||
|       process.stdout.write( |  | ||||||
|         `Skipped test "${removeAuth_removesSshCommand}". Executable 'ssh' not found in the PATH.\n` |  | ||||||
|       ) |  | ||||||
|       return |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(removeAuth_removesSshCommand) |  | ||||||
|     const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
|     await authHelper.configureAuth() |  | ||||||
|     let gitConfigContent = ( |  | ||||||
|       await fs.promises.readFile(localGitConfigPath) |  | ||||||
|     ).toString() |  | ||||||
|     expect(gitConfigContent.indexOf('core.sshCommand')).toBeGreaterThanOrEqual( |  | ||||||
|       0 |  | ||||||
|     ) // sanity check
 |  | ||||||
|     const actualKeyPath = await getActualSshKeyPath() |  | ||||||
|     expect(actualKeyPath).toBeTruthy() |  | ||||||
|     await fs.promises.stat(actualKeyPath) |  | ||||||
|     const actualKnownHostsPath = await getActualSshKnownHostsPath() |  | ||||||
|     expect(actualKnownHostsPath).toBeTruthy() |  | ||||||
|     await fs.promises.stat(actualKnownHostsPath) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await authHelper.removeAuth() |  | ||||||
| 
 |  | ||||||
|     // Assert git config
 |  | ||||||
|     gitConfigContent = ( |  | ||||||
|       await fs.promises.readFile(localGitConfigPath) |  | ||||||
|     ).toString() |  | ||||||
|     expect(gitConfigContent.indexOf('core.sshCommand')).toBeLessThan(0) |  | ||||||
| 
 |  | ||||||
|     // Assert SSH key file
 |  | ||||||
|     try { |  | ||||||
|       await fs.promises.stat(actualKeyPath) |  | ||||||
|       throw new Error('SSH key should have been deleted') |  | ||||||
|     } catch (err) { |  | ||||||
|       if ((err as any)?.code !== 'ENOENT') { |  | ||||||
|         throw err |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Assert known hosts file
 |  | ||||||
|     try { |  | ||||||
|       await fs.promises.stat(actualKnownHostsPath) |  | ||||||
|       throw new Error('SSH known hosts should have been deleted') |  | ||||||
|     } catch (err) { |  | ||||||
|       if ((err as any)?.code !== 'ENOENT') { |  | ||||||
|         throw err |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const removeAuth_removesToken = 'removeAuth removes token' |  | ||||||
|   it(removeAuth_removesToken, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(removeAuth_removesToken) |  | ||||||
|     const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
|     await authHelper.configureAuth() |  | ||||||
|     let gitConfigContent = ( |  | ||||||
|       await fs.promises.readFile(localGitConfigPath) |  | ||||||
|     ).toString() |  | ||||||
|     expect(gitConfigContent.indexOf('http.')).toBeGreaterThanOrEqual(0) // sanity check
 |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await authHelper.removeAuth() |  | ||||||
| 
 |  | ||||||
|     // Assert git config
 |  | ||||||
|     gitConfigContent = ( |  | ||||||
|       await fs.promises.readFile(localGitConfigPath) |  | ||||||
|     ).toString() |  | ||||||
|     expect(gitConfigContent.indexOf('http.')).toBeLessThan(0) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const removeGlobalConfig_removesOverride = |  | ||||||
|     'removeGlobalConfig removes override' |  | ||||||
|   it(removeGlobalConfig_removesOverride, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(removeGlobalConfig_removesOverride) |  | ||||||
|     const authHelper = gitAuthHelper.createAuthHelper(git, settings) |  | ||||||
|     await authHelper.configureAuth() |  | ||||||
|     await authHelper.configureGlobalAuth() |  | ||||||
|     const homeOverride = git.env['HOME'] // Sanity check
 |  | ||||||
|     expect(homeOverride).toBeTruthy() |  | ||||||
|     await fs.promises.stat(path.join(git.env['HOME'], '.gitconfig')) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await authHelper.removeGlobalConfig() |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     expect(git.env['HOME']).toBeUndefined() |  | ||||||
|     try { |  | ||||||
|       await fs.promises.stat(homeOverride) |  | ||||||
|       throw new Error(`Should have been deleted '${homeOverride}'`) |  | ||||||
|     } catch (err) { |  | ||||||
|       if ((err as any)?.code !== 'ENOENT') { |  | ||||||
|         throw err |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
| }) |  | ||||||
| 
 |  | ||||||
| async function setup(testName: string): Promise<void> { |  | ||||||
|   testName = testName.replace(/[^a-zA-Z0-9_]+/g, '-') |  | ||||||
| 
 |  | ||||||
|   // Directories
 |  | ||||||
|   workspace = path.join(testWorkspace, testName, 'workspace') |  | ||||||
|   runnerTemp = path.join(testWorkspace, testName, 'runner-temp') |  | ||||||
|   tempHomedir = path.join(testWorkspace, testName, 'home-dir') |  | ||||||
|   await fs.promises.mkdir(workspace, {recursive: true}) |  | ||||||
|   await fs.promises.mkdir(runnerTemp, {recursive: true}) |  | ||||||
|   await fs.promises.mkdir(tempHomedir, {recursive: true}) |  | ||||||
|   process.env['RUNNER_TEMP'] = runnerTemp |  | ||||||
|   process.env['HOME'] = tempHomedir |  | ||||||
| 
 |  | ||||||
|   // Create git config
 |  | ||||||
|   globalGitConfigPath = path.join(tempHomedir, '.gitconfig') |  | ||||||
|   await fs.promises.writeFile(globalGitConfigPath, '') |  | ||||||
|   localGitConfigPath = path.join(workspace, '.git', 'config') |  | ||||||
|   await fs.promises.mkdir(path.dirname(localGitConfigPath), {recursive: true}) |  | ||||||
|   await fs.promises.writeFile(localGitConfigPath, '') |  | ||||||
| 
 |  | ||||||
|   git = { |  | ||||||
|     branchDelete: jest.fn(), |  | ||||||
|     branchExists: jest.fn(), |  | ||||||
|     branchList: jest.fn(), |  | ||||||
|     disableSparseCheckout: jest.fn(), |  | ||||||
|     sparseCheckout: jest.fn(), |  | ||||||
|     sparseCheckoutNonConeMode: jest.fn(), |  | ||||||
|     checkout: jest.fn(), |  | ||||||
|     checkoutDetach: jest.fn(), |  | ||||||
|     config: jest.fn( |  | ||||||
|       async (key: string, value: string, globalConfig?: boolean) => { |  | ||||||
|         const configPath = globalConfig |  | ||||||
|           ? path.join(git.env['HOME'] || tempHomedir, '.gitconfig') |  | ||||||
|           : localGitConfigPath |  | ||||||
|         await fs.promises.appendFile(configPath, `\n${key} ${value}`) |  | ||||||
|       } |  | ||||||
|     ), |  | ||||||
|     configExists: jest.fn( |  | ||||||
|       async (key: string, globalConfig?: boolean): Promise<boolean> => { |  | ||||||
|         const configPath = globalConfig |  | ||||||
|           ? path.join(git.env['HOME'] || tempHomedir, '.gitconfig') |  | ||||||
|           : localGitConfigPath |  | ||||||
|         const content = await fs.promises.readFile(configPath) |  | ||||||
|         const lines = content |  | ||||||
|           .toString() |  | ||||||
|           .split('\n') |  | ||||||
|           .filter(x => x) |  | ||||||
|         return lines.some(x => x.startsWith(key)) |  | ||||||
|       } |  | ||||||
|     ), |  | ||||||
|     env: {}, |  | ||||||
|     fetch: jest.fn(), |  | ||||||
|     getDefaultBranch: jest.fn(), |  | ||||||
|     getWorkingDirectory: jest.fn(() => workspace), |  | ||||||
|     init: jest.fn(), |  | ||||||
|     isDetached: jest.fn(), |  | ||||||
|     lfsFetch: jest.fn(), |  | ||||||
|     lfsInstall: jest.fn(), |  | ||||||
|     log1: jest.fn(), |  | ||||||
|     remoteAdd: jest.fn(), |  | ||||||
|     removeEnvironmentVariable: jest.fn((name: string) => delete git.env[name]), |  | ||||||
|     revParse: jest.fn(), |  | ||||||
|     setEnvironmentVariable: jest.fn((name: string, value: string) => { |  | ||||||
|       git.env[name] = value |  | ||||||
|     }), |  | ||||||
|     shaExists: jest.fn(), |  | ||||||
|     submoduleForeach: jest.fn(async () => { |  | ||||||
|       return '' |  | ||||||
|     }), |  | ||||||
|     submoduleSync: jest.fn(), |  | ||||||
|     submoduleStatus: jest.fn(async () => { |  | ||||||
|       return true |  | ||||||
|     }), |  | ||||||
|     submoduleUpdate: jest.fn(), |  | ||||||
|     tagExists: jest.fn(), |  | ||||||
|     tryClean: jest.fn(), |  | ||||||
|     tryConfigUnset: jest.fn( |  | ||||||
|       async (key: string, globalConfig?: boolean): Promise<boolean> => { |  | ||||||
|         const configPath = globalConfig |  | ||||||
|           ? path.join(git.env['HOME'] || tempHomedir, '.gitconfig') |  | ||||||
|           : localGitConfigPath |  | ||||||
|         let content = await fs.promises.readFile(configPath) |  | ||||||
|         let lines = content |  | ||||||
|           .toString() |  | ||||||
|           .split('\n') |  | ||||||
|           .filter(x => x) |  | ||||||
|           .filter(x => !x.startsWith(key)) |  | ||||||
|         await fs.promises.writeFile(configPath, lines.join('\n')) |  | ||||||
|         return true |  | ||||||
|       } |  | ||||||
|     ), |  | ||||||
|     tryDisableAutomaticGarbageCollection: jest.fn(), |  | ||||||
|     tryGetFetchUrl: jest.fn(), |  | ||||||
|     tryReset: jest.fn(), |  | ||||||
|     version: jest.fn() |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   settings = { |  | ||||||
|     authToken: 'some auth token', |  | ||||||
|     clean: true, |  | ||||||
|     commit: '', |  | ||||||
|     filter: undefined, |  | ||||||
|     sparseCheckout: [], |  | ||||||
|     sparseCheckoutConeMode: true, |  | ||||||
|     fetchDepth: 1, |  | ||||||
|     fetchTags: false, |  | ||||||
|     showProgress: true, |  | ||||||
|     lfs: false, |  | ||||||
|     submodules: false, |  | ||||||
|     nestedSubmodules: false, |  | ||||||
|     persistCredentials: true, |  | ||||||
|     ref: 'refs/heads/main', |  | ||||||
|     repositoryName: 'my-repo', |  | ||||||
|     repositoryOwner: 'my-org', |  | ||||||
|     repositoryPath: '', |  | ||||||
|     sshKey: sshPath ? 'some ssh private key' : '', |  | ||||||
|     sshKnownHosts: '', |  | ||||||
|     sshStrict: true, |  | ||||||
|     sshUser: '', |  | ||||||
|     workflowOrganizationId: 123456, |  | ||||||
|     setSafeDirectory: true, |  | ||||||
|     githubServerUrl: githubServerUrl |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| async function getActualSshKeyPath(): Promise<string> { |  | ||||||
|   let actualTempFiles = (await fs.promises.readdir(runnerTemp)) |  | ||||||
|     .sort() |  | ||||||
|     .map(x => path.join(runnerTemp, x)) |  | ||||||
|   if (actualTempFiles.length === 0) { |  | ||||||
|     return '' |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   expect(actualTempFiles).toHaveLength(2) |  | ||||||
|   expect(actualTempFiles[0].endsWith('_known_hosts')).toBeFalsy() |  | ||||||
|   return actualTempFiles[0] |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| async function getActualSshKnownHostsPath(): Promise<string> { |  | ||||||
|   let actualTempFiles = (await fs.promises.readdir(runnerTemp)) |  | ||||||
|     .sort() |  | ||||||
|     .map(x => path.join(runnerTemp, x)) |  | ||||||
|   if (actualTempFiles.length === 0) { |  | ||||||
|     return '' |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   expect(actualTempFiles).toHaveLength(2) |  | ||||||
|   expect(actualTempFiles[1].endsWith('_known_hosts')).toBeTruthy() |  | ||||||
|   expect(actualTempFiles[1].startsWith(actualTempFiles[0])).toBeTruthy() |  | ||||||
|   return actualTempFiles[1] |  | ||||||
| } |  | ||||||
|  | @ -1,378 +0,0 @@ | ||||||
| import * as exec from '@actions/exec' |  | ||||||
| import * as fshelper from '../lib/fs-helper' |  | ||||||
| import * as commandManager from '../lib/git-command-manager' |  | ||||||
| 
 |  | ||||||
| let git: commandManager.IGitCommandManager |  | ||||||
| let mockExec = jest.fn() |  | ||||||
| 
 |  | ||||||
| describe('git-auth-helper tests', () => { |  | ||||||
|   beforeAll(async () => {}) |  | ||||||
| 
 |  | ||||||
|   beforeEach(async () => { |  | ||||||
|     jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn()) |  | ||||||
|     jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn()) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   afterEach(() => { |  | ||||||
|     jest.restoreAllMocks() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   afterAll(() => {}) |  | ||||||
| 
 |  | ||||||
|   it('branch list matches', async () => { |  | ||||||
|     mockExec.mockImplementation((path, args, options) => { |  | ||||||
|       console.log(args, options.listeners.stdout) |  | ||||||
| 
 |  | ||||||
|       if (args.includes('version')) { |  | ||||||
|         options.listeners.stdout(Buffer.from('2.18')) |  | ||||||
|         return 0 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (args.includes('rev-parse')) { |  | ||||||
|         options.listeners.stdline(Buffer.from('refs/heads/foo')) |  | ||||||
|         options.listeners.stdline(Buffer.from('refs/heads/bar')) |  | ||||||
|         return 0 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       return 1 |  | ||||||
|     }) |  | ||||||
|     jest.spyOn(exec, 'exec').mockImplementation(mockExec) |  | ||||||
|     const workingDirectory = 'test' |  | ||||||
|     const lfs = false |  | ||||||
|     const doSparseCheckout = false |  | ||||||
|     git = await commandManager.createCommandManager( |  | ||||||
|       workingDirectory, |  | ||||||
|       lfs, |  | ||||||
|       doSparseCheckout |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     let branches = await git.branchList(false) |  | ||||||
| 
 |  | ||||||
|     expect(branches).toHaveLength(2) |  | ||||||
|     expect(branches.sort()).toEqual(['foo', 'bar'].sort()) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('ambiguous ref name output is captured', async () => { |  | ||||||
|     mockExec.mockImplementation((path, args, options) => { |  | ||||||
|       console.log(args, options.listeners.stdout) |  | ||||||
| 
 |  | ||||||
|       if (args.includes('version')) { |  | ||||||
|         options.listeners.stdout(Buffer.from('2.18')) |  | ||||||
|         return 0 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (args.includes('rev-parse')) { |  | ||||||
|         options.listeners.stdline(Buffer.from('refs/heads/foo')) |  | ||||||
|         // If refs/tags/v1 and refs/heads/tags/v1 existed on this repository
 |  | ||||||
|         options.listeners.errline( |  | ||||||
|           Buffer.from("error: refname 'tags/v1' is ambiguous") |  | ||||||
|         ) |  | ||||||
|         return 0 |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       return 1 |  | ||||||
|     }) |  | ||||||
|     jest.spyOn(exec, 'exec').mockImplementation(mockExec) |  | ||||||
|     const workingDirectory = 'test' |  | ||||||
|     const lfs = false |  | ||||||
|     const doSparseCheckout = false |  | ||||||
|     git = await commandManager.createCommandManager( |  | ||||||
|       workingDirectory, |  | ||||||
|       lfs, |  | ||||||
|       doSparseCheckout |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     let branches = await git.branchList(false) |  | ||||||
| 
 |  | ||||||
|     expect(branches).toHaveLength(1) |  | ||||||
|     expect(branches.sort()).toEqual(['foo'].sort()) |  | ||||||
|   }) |  | ||||||
| }) |  | ||||||
| 
 |  | ||||||
| describe('Test fetchDepth and fetchTags options', () => { |  | ||||||
|   beforeEach(async () => { |  | ||||||
|     jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn()) |  | ||||||
|     jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn()) |  | ||||||
|     mockExec.mockImplementation((path, args, options) => { |  | ||||||
|       console.log(args, options.listeners.stdout) |  | ||||||
| 
 |  | ||||||
|       if (args.includes('version')) { |  | ||||||
|         options.listeners.stdout(Buffer.from('2.18')) |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       return 0 |  | ||||||
|     }) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   afterEach(() => { |  | ||||||
|     jest.restoreAllMocks() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('should call execGit with the correct arguments when fetchDepth is 0 and fetchTags is true', async () => { |  | ||||||
|     jest.spyOn(exec, 'exec').mockImplementation(mockExec) |  | ||||||
|     const workingDirectory = 'test' |  | ||||||
|     const lfs = false |  | ||||||
|     const doSparseCheckout = false |  | ||||||
|     git = await commandManager.createCommandManager( |  | ||||||
|       workingDirectory, |  | ||||||
|       lfs, |  | ||||||
|       doSparseCheckout |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     const refSpec = ['refspec1', 'refspec2'] |  | ||||||
|     const options = { |  | ||||||
|       filter: 'filterValue', |  | ||||||
|       fetchDepth: 0, |  | ||||||
|       fetchTags: true |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     await git.fetch(refSpec, options) |  | ||||||
| 
 |  | ||||||
|     expect(mockExec).toHaveBeenCalledWith( |  | ||||||
|       expect.any(String), |  | ||||||
|       [ |  | ||||||
|         '-c', |  | ||||||
|         'protocol.version=2', |  | ||||||
|         'fetch', |  | ||||||
|         '--prune', |  | ||||||
|         '--no-recurse-submodules', |  | ||||||
|         '--filter=filterValue', |  | ||||||
|         'origin', |  | ||||||
|         'refspec1', |  | ||||||
|         'refspec2' |  | ||||||
|       ], |  | ||||||
|       expect.any(Object) |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('should call execGit with the correct arguments when fetchDepth is 0 and fetchTags is false', async () => { |  | ||||||
|     jest.spyOn(exec, 'exec').mockImplementation(mockExec) |  | ||||||
| 
 |  | ||||||
|     const workingDirectory = 'test' |  | ||||||
|     const lfs = false |  | ||||||
|     const doSparseCheckout = false |  | ||||||
|     git = await commandManager.createCommandManager( |  | ||||||
|       workingDirectory, |  | ||||||
|       lfs, |  | ||||||
|       doSparseCheckout |  | ||||||
|     ) |  | ||||||
|     const refSpec = ['refspec1', 'refspec2'] |  | ||||||
|     const options = { |  | ||||||
|       filter: 'filterValue', |  | ||||||
|       fetchDepth: 0, |  | ||||||
|       fetchTags: false |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     await git.fetch(refSpec, options) |  | ||||||
| 
 |  | ||||||
|     expect(mockExec).toHaveBeenCalledWith( |  | ||||||
|       expect.any(String), |  | ||||||
|       [ |  | ||||||
|         '-c', |  | ||||||
|         'protocol.version=2', |  | ||||||
|         'fetch', |  | ||||||
|         '--no-tags', |  | ||||||
|         '--prune', |  | ||||||
|         '--no-recurse-submodules', |  | ||||||
|         '--filter=filterValue', |  | ||||||
|         'origin', |  | ||||||
|         'refspec1', |  | ||||||
|         'refspec2' |  | ||||||
|       ], |  | ||||||
|       expect.any(Object) |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('should call execGit with the correct arguments when fetchDepth is 1 and fetchTags is false', async () => { |  | ||||||
|     jest.spyOn(exec, 'exec').mockImplementation(mockExec) |  | ||||||
| 
 |  | ||||||
|     const workingDirectory = 'test' |  | ||||||
|     const lfs = false |  | ||||||
|     const doSparseCheckout = false |  | ||||||
|     git = await commandManager.createCommandManager( |  | ||||||
|       workingDirectory, |  | ||||||
|       lfs, |  | ||||||
|       doSparseCheckout |  | ||||||
|     ) |  | ||||||
|     const refSpec = ['refspec1', 'refspec2'] |  | ||||||
|     const options = { |  | ||||||
|       filter: 'filterValue', |  | ||||||
|       fetchDepth: 1, |  | ||||||
|       fetchTags: false |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     await git.fetch(refSpec, options) |  | ||||||
| 
 |  | ||||||
|     expect(mockExec).toHaveBeenCalledWith( |  | ||||||
|       expect.any(String), |  | ||||||
|       [ |  | ||||||
|         '-c', |  | ||||||
|         'protocol.version=2', |  | ||||||
|         'fetch', |  | ||||||
|         '--no-tags', |  | ||||||
|         '--prune', |  | ||||||
|         '--no-recurse-submodules', |  | ||||||
|         '--filter=filterValue', |  | ||||||
|         '--depth=1', |  | ||||||
|         'origin', |  | ||||||
|         'refspec1', |  | ||||||
|         'refspec2' |  | ||||||
|       ], |  | ||||||
|       expect.any(Object) |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('should call execGit with the correct arguments when fetchDepth is 1 and fetchTags is true', async () => { |  | ||||||
|     jest.spyOn(exec, 'exec').mockImplementation(mockExec) |  | ||||||
| 
 |  | ||||||
|     const workingDirectory = 'test' |  | ||||||
|     const lfs = false |  | ||||||
|     const doSparseCheckout = false |  | ||||||
|     git = await commandManager.createCommandManager( |  | ||||||
|       workingDirectory, |  | ||||||
|       lfs, |  | ||||||
|       doSparseCheckout |  | ||||||
|     ) |  | ||||||
|     const refSpec = ['refspec1', 'refspec2'] |  | ||||||
|     const options = { |  | ||||||
|       filter: 'filterValue', |  | ||||||
|       fetchDepth: 1, |  | ||||||
|       fetchTags: true |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     await git.fetch(refSpec, options) |  | ||||||
| 
 |  | ||||||
|     expect(mockExec).toHaveBeenCalledWith( |  | ||||||
|       expect.any(String), |  | ||||||
|       [ |  | ||||||
|         '-c', |  | ||||||
|         'protocol.version=2', |  | ||||||
|         'fetch', |  | ||||||
|         '--prune', |  | ||||||
|         '--no-recurse-submodules', |  | ||||||
|         '--filter=filterValue', |  | ||||||
|         '--depth=1', |  | ||||||
|         'origin', |  | ||||||
|         'refspec1', |  | ||||||
|         'refspec2' |  | ||||||
|       ], |  | ||||||
|       expect.any(Object) |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('should call execGit with the correct arguments when showProgress is true', async () => { |  | ||||||
|     jest.spyOn(exec, 'exec').mockImplementation(mockExec) |  | ||||||
| 
 |  | ||||||
|     const workingDirectory = 'test' |  | ||||||
|     const lfs = false |  | ||||||
|     const doSparseCheckout = false |  | ||||||
|     git = await commandManager.createCommandManager( |  | ||||||
|       workingDirectory, |  | ||||||
|       lfs, |  | ||||||
|       doSparseCheckout |  | ||||||
|     ) |  | ||||||
|     const refSpec = ['refspec1', 'refspec2'] |  | ||||||
|     const options = { |  | ||||||
|       filter: 'filterValue', |  | ||||||
|       showProgress: true |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     await git.fetch(refSpec, options) |  | ||||||
| 
 |  | ||||||
|     expect(mockExec).toHaveBeenCalledWith( |  | ||||||
|       expect.any(String), |  | ||||||
|       [ |  | ||||||
|         '-c', |  | ||||||
|         'protocol.version=2', |  | ||||||
|         'fetch', |  | ||||||
|         '--no-tags', |  | ||||||
|         '--prune', |  | ||||||
|         '--no-recurse-submodules', |  | ||||||
|         '--progress', |  | ||||||
|         '--filter=filterValue', |  | ||||||
|         'origin', |  | ||||||
|         'refspec1', |  | ||||||
|         'refspec2' |  | ||||||
|       ], |  | ||||||
|       expect.any(Object) |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('should call execGit with the correct arguments when fetchDepth is 42 and showProgress is true', async () => { |  | ||||||
|     jest.spyOn(exec, 'exec').mockImplementation(mockExec) |  | ||||||
| 
 |  | ||||||
|     const workingDirectory = 'test' |  | ||||||
|     const lfs = false |  | ||||||
|     const doSparseCheckout = false |  | ||||||
|     git = await commandManager.createCommandManager( |  | ||||||
|       workingDirectory, |  | ||||||
|       lfs, |  | ||||||
|       doSparseCheckout |  | ||||||
|     ) |  | ||||||
|     const refSpec = ['refspec1', 'refspec2'] |  | ||||||
|     const options = { |  | ||||||
|       filter: 'filterValue', |  | ||||||
|       fetchDepth: 42, |  | ||||||
|       showProgress: true |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     await git.fetch(refSpec, options) |  | ||||||
| 
 |  | ||||||
|     expect(mockExec).toHaveBeenCalledWith( |  | ||||||
|       expect.any(String), |  | ||||||
|       [ |  | ||||||
|         '-c', |  | ||||||
|         'protocol.version=2', |  | ||||||
|         'fetch', |  | ||||||
|         '--no-tags', |  | ||||||
|         '--prune', |  | ||||||
|         '--no-recurse-submodules', |  | ||||||
|         '--progress', |  | ||||||
|         '--filter=filterValue', |  | ||||||
|         '--depth=42', |  | ||||||
|         'origin', |  | ||||||
|         'refspec1', |  | ||||||
|         'refspec2' |  | ||||||
|       ], |  | ||||||
|       expect.any(Object) |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('should call execGit with the correct arguments when fetchTags is true and showProgress is true', async () => { |  | ||||||
|     jest.spyOn(exec, 'exec').mockImplementation(mockExec) |  | ||||||
| 
 |  | ||||||
|     const workingDirectory = 'test' |  | ||||||
|     const lfs = false |  | ||||||
|     const doSparseCheckout = false |  | ||||||
|     git = await commandManager.createCommandManager( |  | ||||||
|       workingDirectory, |  | ||||||
|       lfs, |  | ||||||
|       doSparseCheckout |  | ||||||
|     ) |  | ||||||
|     const refSpec = ['refspec1', 'refspec2'] |  | ||||||
|     const options = { |  | ||||||
|       filter: 'filterValue', |  | ||||||
|       fetchTags: true, |  | ||||||
|       showProgress: true |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     await git.fetch(refSpec, options) |  | ||||||
| 
 |  | ||||||
|     expect(mockExec).toHaveBeenCalledWith( |  | ||||||
|       expect.any(String), |  | ||||||
|       [ |  | ||||||
|         '-c', |  | ||||||
|         'protocol.version=2', |  | ||||||
|         'fetch', |  | ||||||
|         '--prune', |  | ||||||
|         '--no-recurse-submodules', |  | ||||||
|         '--progress', |  | ||||||
|         '--filter=filterValue', |  | ||||||
|         'origin', |  | ||||||
|         'refspec1', |  | ||||||
|         'refspec2' |  | ||||||
|       ], |  | ||||||
|       expect.any(Object) |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| }) |  | ||||||
|  | @ -1,507 +0,0 @@ | ||||||
| import * as core from '@actions/core' |  | ||||||
| import * as fs from 'fs' |  | ||||||
| import * as gitDirectoryHelper from '../lib/git-directory-helper' |  | ||||||
| import * as io from '@actions/io' |  | ||||||
| import * as path from 'path' |  | ||||||
| import {IGitCommandManager} from '../lib/git-command-manager' |  | ||||||
| 
 |  | ||||||
| const testWorkspace = path.join(__dirname, '_temp', 'git-directory-helper') |  | ||||||
| let repositoryPath: string |  | ||||||
| let repositoryUrl: string |  | ||||||
| let clean: boolean |  | ||||||
| let ref: string |  | ||||||
| let git: IGitCommandManager |  | ||||||
| 
 |  | ||||||
| describe('git-directory-helper tests', () => { |  | ||||||
|   beforeAll(async () => { |  | ||||||
|     // Clear test workspace
 |  | ||||||
|     await io.rmRF(testWorkspace) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   beforeEach(() => { |  | ||||||
|     // Mock error/warning/info/debug
 |  | ||||||
|     jest.spyOn(core, 'error').mockImplementation(jest.fn()) |  | ||||||
|     jest.spyOn(core, 'warning').mockImplementation(jest.fn()) |  | ||||||
|     jest.spyOn(core, 'info').mockImplementation(jest.fn()) |  | ||||||
|     jest.spyOn(core, 'debug').mockImplementation(jest.fn()) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   afterEach(() => { |  | ||||||
|     // Unregister mocks
 |  | ||||||
|     jest.restoreAllMocks() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const cleansWhenCleanTrue = 'cleans when clean true' |  | ||||||
|   it(cleansWhenCleanTrue, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(cleansWhenCleanTrue) |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files.sort()).toEqual(['.git', 'my-file']) |  | ||||||
|     expect(git.tryClean).toHaveBeenCalled() |  | ||||||
|     expect(git.tryReset).toHaveBeenCalled() |  | ||||||
|     expect(core.warning).not.toHaveBeenCalled() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const checkoutDetachWhenNotDetached = 'checkout detach when not detached' |  | ||||||
|   it(checkoutDetachWhenNotDetached, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(checkoutDetachWhenNotDetached) |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files.sort()).toEqual(['.git', 'my-file']) |  | ||||||
|     expect(git.checkoutDetach).toHaveBeenCalled() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const doesNotCheckoutDetachWhenNotAlreadyDetached = |  | ||||||
|     'does not checkout detach when already detached' |  | ||||||
|   it(doesNotCheckoutDetachWhenNotAlreadyDetached, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(doesNotCheckoutDetachWhenNotAlreadyDetached) |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
|     const mockIsDetached = git.isDetached as jest.Mock<any, any> |  | ||||||
|     mockIsDetached.mockImplementation(async () => { |  | ||||||
|       return true |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files.sort()).toEqual(['.git', 'my-file']) |  | ||||||
|     expect(git.checkoutDetach).not.toHaveBeenCalled() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const doesNotCleanWhenCleanFalse = 'does not clean when clean false' |  | ||||||
|   it(doesNotCleanWhenCleanFalse, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(doesNotCleanWhenCleanFalse) |  | ||||||
|     clean = false |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files.sort()).toEqual(['.git', 'my-file']) |  | ||||||
|     expect(git.isDetached).toHaveBeenCalled() |  | ||||||
|     expect(git.branchList).toHaveBeenCalled() |  | ||||||
|     expect(core.warning).not.toHaveBeenCalled() |  | ||||||
|     expect(git.tryClean).not.toHaveBeenCalled() |  | ||||||
|     expect(git.tryReset).not.toHaveBeenCalled() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const removesContentsWhenCleanFails = 'removes contents when clean fails' |  | ||||||
|   it(removesContentsWhenCleanFails, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(removesContentsWhenCleanFails) |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
|     let mockTryClean = git.tryClean as jest.Mock<any, any> |  | ||||||
|     mockTryClean.mockImplementation(async () => { |  | ||||||
|       return false |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files).toHaveLength(0) |  | ||||||
|     expect(git.tryClean).toHaveBeenCalled() |  | ||||||
|     expect(core.warning).toHaveBeenCalled() |  | ||||||
|     expect(git.tryReset).not.toHaveBeenCalled() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const removesContentsWhenDifferentRepositoryUrl = |  | ||||||
|     'removes contents when different repository url' |  | ||||||
|   it(removesContentsWhenDifferentRepositoryUrl, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(removesContentsWhenDifferentRepositoryUrl) |  | ||||||
|     clean = false |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
|     const differentRepositoryUrl = |  | ||||||
|       'https://github.com/my-different-org/my-different-repo' |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       differentRepositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files).toHaveLength(0) |  | ||||||
|     expect(core.warning).not.toHaveBeenCalled() |  | ||||||
|     expect(git.isDetached).not.toHaveBeenCalled() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const removesContentsWhenNoGitDirectory = |  | ||||||
|     'removes contents when no git directory' |  | ||||||
|   it(removesContentsWhenNoGitDirectory, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(removesContentsWhenNoGitDirectory) |  | ||||||
|     clean = false |  | ||||||
|     await io.rmRF(path.join(repositoryPath, '.git')) |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files).toHaveLength(0) |  | ||||||
|     expect(core.warning).not.toHaveBeenCalled() |  | ||||||
|     expect(git.isDetached).not.toHaveBeenCalled() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const removesContentsWhenResetFails = 'removes contents when reset fails' |  | ||||||
|   it(removesContentsWhenResetFails, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(removesContentsWhenResetFails) |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
|     let mockTryReset = git.tryReset as jest.Mock<any, any> |  | ||||||
|     mockTryReset.mockImplementation(async () => { |  | ||||||
|       return false |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files).toHaveLength(0) |  | ||||||
|     expect(git.tryClean).toHaveBeenCalled() |  | ||||||
|     expect(git.tryReset).toHaveBeenCalled() |  | ||||||
|     expect(core.warning).toHaveBeenCalled() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const removesContentsWhenUndefinedGitCommandManager = |  | ||||||
|     'removes contents when undefined git command manager' |  | ||||||
|   it(removesContentsWhenUndefinedGitCommandManager, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(removesContentsWhenUndefinedGitCommandManager) |  | ||||||
|     clean = false |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       undefined, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files).toHaveLength(0) |  | ||||||
|     expect(core.warning).not.toHaveBeenCalled() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const removesLocalBranches = 'removes local branches' |  | ||||||
|   it(removesLocalBranches, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(removesLocalBranches) |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
|     const mockBranchList = git.branchList as jest.Mock<any, any> |  | ||||||
|     mockBranchList.mockImplementation(async (remote: boolean) => { |  | ||||||
|       return remote ? [] : ['local-branch-1', 'local-branch-2'] |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files.sort()).toEqual(['.git', 'my-file']) |  | ||||||
|     expect(git.branchDelete).toHaveBeenCalledWith(false, 'local-branch-1') |  | ||||||
|     expect(git.branchDelete).toHaveBeenCalledWith(false, 'local-branch-2') |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const cleanWhenSubmoduleStatusIsFalse = |  | ||||||
|     'cleans when submodule status is false' |  | ||||||
| 
 |  | ||||||
|   it(cleanWhenSubmoduleStatusIsFalse, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(cleanWhenSubmoduleStatusIsFalse) |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
| 
 |  | ||||||
|     //mock bad submodule
 |  | ||||||
| 
 |  | ||||||
|     const submoduleStatus = git.submoduleStatus as jest.Mock<any, any> |  | ||||||
|     submoduleStatus.mockImplementation(async (remote: boolean) => { |  | ||||||
|       return false |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files).toHaveLength(0) |  | ||||||
|     expect(git.tryClean).toHaveBeenCalled() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const doesNotCleanWhenSubmoduleStatusIsTrue = |  | ||||||
|     'does not clean when submodule status is true' |  | ||||||
| 
 |  | ||||||
|   it(doesNotCleanWhenSubmoduleStatusIsTrue, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(doesNotCleanWhenSubmoduleStatusIsTrue) |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
| 
 |  | ||||||
|     const submoduleStatus = git.submoduleStatus as jest.Mock<any, any> |  | ||||||
|     submoduleStatus.mockImplementation(async (remote: boolean) => { |  | ||||||
|       return true |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
| 
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files.sort()).toEqual(['.git', 'my-file']) |  | ||||||
|     expect(git.tryClean).toHaveBeenCalled() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const removesLockFiles = 'removes lock files' |  | ||||||
|   it(removesLockFiles, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(removesLockFiles) |  | ||||||
|     clean = false |  | ||||||
|     await fs.promises.writeFile( |  | ||||||
|       path.join(repositoryPath, '.git', 'index.lock'), |  | ||||||
|       '' |  | ||||||
|     ) |  | ||||||
|     await fs.promises.writeFile( |  | ||||||
|       path.join(repositoryPath, '.git', 'shallow.lock'), |  | ||||||
|       '' |  | ||||||
|     ) |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     let files = await fs.promises.readdir(path.join(repositoryPath, '.git')) |  | ||||||
|     expect(files).toHaveLength(0) |  | ||||||
|     files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files.sort()).toEqual(['.git', 'my-file']) |  | ||||||
|     expect(git.isDetached).toHaveBeenCalled() |  | ||||||
|     expect(git.branchList).toHaveBeenCalled() |  | ||||||
|     expect(core.warning).not.toHaveBeenCalled() |  | ||||||
|     expect(git.tryClean).not.toHaveBeenCalled() |  | ||||||
|     expect(git.tryReset).not.toHaveBeenCalled() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const removesAncestorRemoteBranch = 'removes ancestor remote branch' |  | ||||||
|   it(removesAncestorRemoteBranch, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(removesAncestorRemoteBranch) |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
|     const mockBranchList = git.branchList as jest.Mock<any, any> |  | ||||||
|     mockBranchList.mockImplementation(async (remote: boolean) => { |  | ||||||
|       return remote ? ['origin/remote-branch-1', 'origin/remote-branch-2'] : [] |  | ||||||
|     }) |  | ||||||
|     ref = 'remote-branch-1/conflict' |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files.sort()).toEqual(['.git', 'my-file']) |  | ||||||
|     expect(git.branchDelete).toHaveBeenCalledTimes(1) |  | ||||||
|     expect(git.branchDelete).toHaveBeenCalledWith( |  | ||||||
|       true, |  | ||||||
|       'origin/remote-branch-1' |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   const removesDescendantRemoteBranches = 'removes descendant remote branch' |  | ||||||
|   it(removesDescendantRemoteBranches, async () => { |  | ||||||
|     // Arrange
 |  | ||||||
|     await setup(removesDescendantRemoteBranches) |  | ||||||
|     await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') |  | ||||||
|     const mockBranchList = git.branchList as jest.Mock<any, any> |  | ||||||
|     mockBranchList.mockImplementation(async (remote: boolean) => { |  | ||||||
|       return remote |  | ||||||
|         ? ['origin/remote-branch-1/conflict', 'origin/remote-branch-2'] |  | ||||||
|         : [] |  | ||||||
|     }) |  | ||||||
|     ref = 'remote-branch-1' |  | ||||||
| 
 |  | ||||||
|     // Act
 |  | ||||||
|     await gitDirectoryHelper.prepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       clean, |  | ||||||
|       ref |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // Assert
 |  | ||||||
|     const files = await fs.promises.readdir(repositoryPath) |  | ||||||
|     expect(files.sort()).toEqual(['.git', 'my-file']) |  | ||||||
|     expect(git.branchDelete).toHaveBeenCalledTimes(1) |  | ||||||
|     expect(git.branchDelete).toHaveBeenCalledWith( |  | ||||||
|       true, |  | ||||||
|       'origin/remote-branch-1/conflict' |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| }) |  | ||||||
| 
 |  | ||||||
| async function setup(testName: string): Promise<void> { |  | ||||||
|   testName = testName.replace(/[^a-zA-Z0-9_]+/g, '-') |  | ||||||
| 
 |  | ||||||
|   // Repository directory
 |  | ||||||
|   repositoryPath = path.join(testWorkspace, testName) |  | ||||||
|   await fs.promises.mkdir(path.join(repositoryPath, '.git'), {recursive: true}) |  | ||||||
| 
 |  | ||||||
|   // Repository URL
 |  | ||||||
|   repositoryUrl = 'https://github.com/my-org/my-repo' |  | ||||||
| 
 |  | ||||||
|   // Clean
 |  | ||||||
|   clean = true |  | ||||||
| 
 |  | ||||||
|   // Ref
 |  | ||||||
|   ref = '' |  | ||||||
| 
 |  | ||||||
|   // Git command manager
 |  | ||||||
|   git = { |  | ||||||
|     branchDelete: jest.fn(), |  | ||||||
|     branchExists: jest.fn(), |  | ||||||
|     branchList: jest.fn(async () => { |  | ||||||
|       return [] |  | ||||||
|     }), |  | ||||||
|     disableSparseCheckout: jest.fn(), |  | ||||||
|     sparseCheckout: jest.fn(), |  | ||||||
|     sparseCheckoutNonConeMode: jest.fn(), |  | ||||||
|     checkout: jest.fn(), |  | ||||||
|     checkoutDetach: jest.fn(), |  | ||||||
|     config: jest.fn(), |  | ||||||
|     configExists: jest.fn(), |  | ||||||
|     fetch: jest.fn(), |  | ||||||
|     getDefaultBranch: jest.fn(), |  | ||||||
|     getWorkingDirectory: jest.fn(() => repositoryPath), |  | ||||||
|     init: jest.fn(), |  | ||||||
|     isDetached: jest.fn(), |  | ||||||
|     lfsFetch: jest.fn(), |  | ||||||
|     lfsInstall: jest.fn(), |  | ||||||
|     log1: jest.fn(), |  | ||||||
|     remoteAdd: jest.fn(), |  | ||||||
|     removeEnvironmentVariable: jest.fn(), |  | ||||||
|     revParse: jest.fn(), |  | ||||||
|     setEnvironmentVariable: jest.fn(), |  | ||||||
|     shaExists: jest.fn(), |  | ||||||
|     submoduleForeach: jest.fn(), |  | ||||||
|     submoduleSync: jest.fn(), |  | ||||||
|     submoduleUpdate: jest.fn(), |  | ||||||
|     submoduleStatus: jest.fn(async () => { |  | ||||||
|       return true |  | ||||||
|     }), |  | ||||||
|     tagExists: jest.fn(), |  | ||||||
|     tryClean: jest.fn(async () => { |  | ||||||
|       return true |  | ||||||
|     }), |  | ||||||
|     tryConfigUnset: jest.fn(), |  | ||||||
|     tryDisableAutomaticGarbageCollection: jest.fn(), |  | ||||||
|     tryGetFetchUrl: jest.fn(async () => { |  | ||||||
|       // Sanity check - this function shouldn't be called when the .git directory doesn't exist
 |  | ||||||
|       await fs.promises.stat(path.join(repositoryPath, '.git')) |  | ||||||
|       return repositoryUrl |  | ||||||
|     }), |  | ||||||
|     tryReset: jest.fn(async () => { |  | ||||||
|       return true |  | ||||||
|     }), |  | ||||||
|     version: jest.fn() |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  | @ -1,86 +0,0 @@ | ||||||
| import {GitVersion} from '../src/git-version' |  | ||||||
| import {MinimumGitSparseCheckoutVersion} from '../src/git-command-manager' |  | ||||||
| 
 |  | ||||||
| describe('git-version tests', () => { |  | ||||||
|   it('basics', async () => { |  | ||||||
|     let version = new GitVersion('') |  | ||||||
|     expect(version.isValid()).toBeFalsy() |  | ||||||
| 
 |  | ||||||
|     version = new GitVersion('asdf') |  | ||||||
|     expect(version.isValid()).toBeFalsy() |  | ||||||
| 
 |  | ||||||
|     version = new GitVersion('1.2') |  | ||||||
|     expect(version.isValid()).toBeTruthy() |  | ||||||
|     expect(version.toString()).toBe('1.2') |  | ||||||
| 
 |  | ||||||
|     version = new GitVersion('1.2.3') |  | ||||||
|     expect(version.isValid()).toBeTruthy() |  | ||||||
|     expect(version.toString()).toBe('1.2.3') |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('check minimum', async () => { |  | ||||||
|     let version = new GitVersion('4.5') |  | ||||||
|     expect(version.checkMinimum(new GitVersion('3.6'))).toBeTruthy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('3.6.7'))).toBeTruthy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('4.4'))).toBeTruthy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('4.5'))).toBeTruthy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('4.5.0'))).toBeTruthy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('4.6'))).toBeFalsy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('4.6.0'))).toBeFalsy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('5.1'))).toBeFalsy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('5.1.2'))).toBeFalsy() |  | ||||||
| 
 |  | ||||||
|     version = new GitVersion('4.5.6') |  | ||||||
|     expect(version.checkMinimum(new GitVersion('3.6'))).toBeTruthy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('3.6.7'))).toBeTruthy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('4.4'))).toBeTruthy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('4.5'))).toBeTruthy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('4.5.5'))).toBeTruthy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('4.5.6'))).toBeTruthy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('4.5.7'))).toBeFalsy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('4.6'))).toBeFalsy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('4.6.0'))).toBeFalsy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('5.1'))).toBeFalsy() |  | ||||||
|     expect(version.checkMinimum(new GitVersion('5.1.2'))).toBeFalsy() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('sparse checkout', async () => { |  | ||||||
|     const minSparseVer = MinimumGitSparseCheckoutVersion |  | ||||||
|     expect(new GitVersion('1.0').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('1.99').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.0').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.24').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.24.0').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.24.9').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.25').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.25.0').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.25.1').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.25.9').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.26').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.26.0').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.26.1').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.26.9').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.27').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.27.0').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.27.1').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     expect(new GitVersion('2.27.9').checkMinimum(minSparseVer)).toBeFalsy() |  | ||||||
|     //                             /---------------------------------------
 |  | ||||||
|     //         ^^^ before         /         after vvv
 |  | ||||||
|     // --------------------------/
 |  | ||||||
|     expect(new GitVersion('2.28').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('2.28.0').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('2.28.1').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('2.28.9').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('2.29').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('2.29.0').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('2.29.1').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('2.29.9').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('2.99').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('3.0').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('3.99').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('4.0').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('4.99').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('5.0').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|     expect(new GitVersion('5.99').checkMinimum(minSparseVer)).toBeTruthy() |  | ||||||
|   }) |  | ||||||
| }) |  | ||||||
|  | @ -1,147 +0,0 @@ | ||||||
| import * as core from '@actions/core' |  | ||||||
| import * as fsHelper from '../lib/fs-helper' |  | ||||||
| import * as github from '@actions/github' |  | ||||||
| import * as inputHelper from '../lib/input-helper' |  | ||||||
| import * as path from 'path' |  | ||||||
| import * as workflowContextHelper from '../lib/workflow-context-helper' |  | ||||||
| import {IGitSourceSettings} from '../lib/git-source-settings' |  | ||||||
| 
 |  | ||||||
| const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE'] |  | ||||||
| const gitHubWorkspace = path.resolve('/checkout-tests/workspace') |  | ||||||
| 
 |  | ||||||
| // Inputs for mock @actions/core
 |  | ||||||
| let inputs = {} as any |  | ||||||
| 
 |  | ||||||
| // Shallow clone original @actions/github context
 |  | ||||||
| let originalContext = {...github.context} |  | ||||||
| 
 |  | ||||||
| describe('input-helper tests', () => { |  | ||||||
|   beforeAll(() => { |  | ||||||
|     // Mock getInput
 |  | ||||||
|     jest.spyOn(core, 'getInput').mockImplementation((name: string) => { |  | ||||||
|       return inputs[name] |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|     // Mock error/warning/info/debug
 |  | ||||||
|     jest.spyOn(core, 'error').mockImplementation(jest.fn()) |  | ||||||
|     jest.spyOn(core, 'warning').mockImplementation(jest.fn()) |  | ||||||
|     jest.spyOn(core, 'info').mockImplementation(jest.fn()) |  | ||||||
|     jest.spyOn(core, 'debug').mockImplementation(jest.fn()) |  | ||||||
| 
 |  | ||||||
|     // Mock github context
 |  | ||||||
|     jest.spyOn(github.context, 'repo', 'get').mockImplementation(() => { |  | ||||||
|       return { |  | ||||||
|         owner: 'some-owner', |  | ||||||
|         repo: 'some-repo' |  | ||||||
|       } |  | ||||||
|     }) |  | ||||||
|     github.context.ref = 'refs/heads/some-ref' |  | ||||||
|     github.context.sha = '1234567890123456789012345678901234567890' |  | ||||||
| 
 |  | ||||||
|     // Mock ./fs-helper directoryExistsSync()
 |  | ||||||
|     jest |  | ||||||
|       .spyOn(fsHelper, 'directoryExistsSync') |  | ||||||
|       .mockImplementation((path: string) => path == gitHubWorkspace) |  | ||||||
| 
 |  | ||||||
|     // Mock ./workflowContextHelper getOrganizationId()
 |  | ||||||
|     jest |  | ||||||
|       .spyOn(workflowContextHelper, 'getOrganizationId') |  | ||||||
|       .mockImplementation(() => Promise.resolve(123456)) |  | ||||||
| 
 |  | ||||||
|     // GitHub workspace
 |  | ||||||
|     process.env['GITHUB_WORKSPACE'] = gitHubWorkspace |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   beforeEach(() => { |  | ||||||
|     // Reset inputs
 |  | ||||||
|     inputs = {} |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   afterAll(() => { |  | ||||||
|     // Restore GitHub workspace
 |  | ||||||
|     delete process.env['GITHUB_WORKSPACE'] |  | ||||||
|     if (originalGitHubWorkspace) { |  | ||||||
|       process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Restore @actions/github context
 |  | ||||||
|     github.context.ref = originalContext.ref |  | ||||||
|     github.context.sha = originalContext.sha |  | ||||||
| 
 |  | ||||||
|     // Restore
 |  | ||||||
|     jest.restoreAllMocks() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('sets defaults', async () => { |  | ||||||
|     const settings: IGitSourceSettings = await inputHelper.getInputs() |  | ||||||
|     expect(settings).toBeTruthy() |  | ||||||
|     expect(settings.authToken).toBeFalsy() |  | ||||||
|     expect(settings.clean).toBe(true) |  | ||||||
|     expect(settings.commit).toBeTruthy() |  | ||||||
|     expect(settings.commit).toBe('1234567890123456789012345678901234567890') |  | ||||||
|     expect(settings.filter).toBe(undefined) |  | ||||||
|     expect(settings.sparseCheckout).toBe(undefined) |  | ||||||
|     expect(settings.sparseCheckoutConeMode).toBe(true) |  | ||||||
|     expect(settings.fetchDepth).toBe(1) |  | ||||||
|     expect(settings.fetchTags).toBe(false) |  | ||||||
|     expect(settings.showProgress).toBe(true) |  | ||||||
|     expect(settings.lfs).toBe(false) |  | ||||||
|     expect(settings.ref).toBe('refs/heads/some-ref') |  | ||||||
|     expect(settings.repositoryName).toBe('some-repo') |  | ||||||
|     expect(settings.repositoryOwner).toBe('some-owner') |  | ||||||
|     expect(settings.repositoryPath).toBe(gitHubWorkspace) |  | ||||||
|     expect(settings.setSafeDirectory).toBe(true) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('qualifies ref', async () => { |  | ||||||
|     let originalRef = github.context.ref |  | ||||||
|     try { |  | ||||||
|       github.context.ref = 'some-unqualified-ref' |  | ||||||
|       const settings: IGitSourceSettings = await inputHelper.getInputs() |  | ||||||
|       expect(settings).toBeTruthy() |  | ||||||
|       expect(settings.commit).toBe('1234567890123456789012345678901234567890') |  | ||||||
|       expect(settings.ref).toBe('refs/heads/some-unqualified-ref') |  | ||||||
|     } finally { |  | ||||||
|       github.context.ref = originalRef |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('requires qualified repo', async () => { |  | ||||||
|     inputs.repository = 'some-unqualified-repo' |  | ||||||
|     try { |  | ||||||
|       await inputHelper.getInputs() |  | ||||||
|       throw 'should not reach here' |  | ||||||
|     } catch (err) { |  | ||||||
|       expect(`(${(err as any).message}`).toMatch( |  | ||||||
|         "Invalid repository 'some-unqualified-repo'" |  | ||||||
|       ) |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('roots path', async () => { |  | ||||||
|     inputs.path = 'some-directory/some-subdirectory' |  | ||||||
|     const settings: IGitSourceSettings = await inputHelper.getInputs() |  | ||||||
|     expect(settings.repositoryPath).toBe( |  | ||||||
|       path.join(gitHubWorkspace, 'some-directory', 'some-subdirectory') |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('sets ref to empty when explicit sha', async () => { |  | ||||||
|     inputs.ref = '1111111111222222222233333333334444444444' |  | ||||||
|     const settings: IGitSourceSettings = await inputHelper.getInputs() |  | ||||||
|     expect(settings.ref).toBeFalsy() |  | ||||||
|     expect(settings.commit).toBe('1111111111222222222233333333334444444444') |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('sets sha to empty when explicit ref', async () => { |  | ||||||
|     inputs.ref = 'refs/heads/some-other-ref' |  | ||||||
|     const settings: IGitSourceSettings = await inputHelper.getInputs() |  | ||||||
|     expect(settings.ref).toBe('refs/heads/some-other-ref') |  | ||||||
|     expect(settings.commit).toBeFalsy() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('sets workflow organization ID', async () => { |  | ||||||
|     const settings: IGitSourceSettings = await inputHelper.getInputs() |  | ||||||
|     expect(settings.workflowOrganizationId).toBe(123456) |  | ||||||
|   }) |  | ||||||
| }) |  | ||||||
|  | @ -1,10 +0,0 @@ | ||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| if [ ! -f "./basic/basic-file.txt" ]; then |  | ||||||
|     echo "Expected basic file does not exist" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| echo hello >> ./basic/basic-file.txt |  | ||||||
| echo hello >> ./basic/new-file.txt |  | ||||||
| git -C ./basic status |  | ||||||
|  | @ -1,6 +0,0 @@ | ||||||
| 
 |  | ||||||
| mkdir override-git-version |  | ||||||
| cd override-git-version |  | ||||||
| echo @echo override git version 1.2.3 > git.cmd |  | ||||||
| echo "%CD%" >> $GITHUB_PATH |  | ||||||
| cd .. |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| mkdir override-git-version |  | ||||||
| cd override-git-version |  | ||||||
| echo "#!/bin/sh" > git |  | ||||||
| echo "echo override git version 1.2.3" >> git |  | ||||||
| chmod +x git |  | ||||||
| echo "$(pwd)" >> $GITHUB_PATH |  | ||||||
| cd .. |  | ||||||
|  | @ -1,190 +0,0 @@ | ||||||
| import * as assert from 'assert' |  | ||||||
| import * as refHelper from '../lib/ref-helper' |  | ||||||
| import {IGitCommandManager} from '../lib/git-command-manager' |  | ||||||
| 
 |  | ||||||
| const commit = '1234567890123456789012345678901234567890' |  | ||||||
| let git: IGitCommandManager |  | ||||||
| 
 |  | ||||||
| describe('ref-helper tests', () => { |  | ||||||
|   beforeEach(() => { |  | ||||||
|     git = {} as unknown as IGitCommandManager |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getCheckoutInfo requires git', async () => { |  | ||||||
|     const git = null as unknown as IGitCommandManager |  | ||||||
|     try { |  | ||||||
|       await refHelper.getCheckoutInfo(git, 'refs/heads/my/branch', commit) |  | ||||||
|       throw new Error('Should not reach here') |  | ||||||
|     } catch (err) { |  | ||||||
|       expect((err as any)?.message).toBe('Arg git cannot be empty') |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getCheckoutInfo requires ref or commit', async () => { |  | ||||||
|     try { |  | ||||||
|       await refHelper.getCheckoutInfo(git, '', '') |  | ||||||
|       throw new Error('Should not reach here') |  | ||||||
|     } catch (err) { |  | ||||||
|       expect((err as any)?.message).toBe( |  | ||||||
|         'Args ref and commit cannot both be empty' |  | ||||||
|       ) |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getCheckoutInfo sha only', async () => { |  | ||||||
|     const checkoutInfo = await refHelper.getCheckoutInfo(git, '', commit) |  | ||||||
|     expect(checkoutInfo.ref).toBe(commit) |  | ||||||
|     expect(checkoutInfo.startPoint).toBeFalsy() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getCheckoutInfo refs/heads/', async () => { |  | ||||||
|     const checkoutInfo = await refHelper.getCheckoutInfo( |  | ||||||
|       git, |  | ||||||
|       'refs/heads/my/branch', |  | ||||||
|       commit |  | ||||||
|     ) |  | ||||||
|     expect(checkoutInfo.ref).toBe('my/branch') |  | ||||||
|     expect(checkoutInfo.startPoint).toBe('refs/remotes/origin/my/branch') |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getCheckoutInfo refs/pull/', async () => { |  | ||||||
|     const checkoutInfo = await refHelper.getCheckoutInfo( |  | ||||||
|       git, |  | ||||||
|       'refs/pull/123/merge', |  | ||||||
|       commit |  | ||||||
|     ) |  | ||||||
|     expect(checkoutInfo.ref).toBe('refs/remotes/pull/123/merge') |  | ||||||
|     expect(checkoutInfo.startPoint).toBeFalsy() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getCheckoutInfo refs/tags/', async () => { |  | ||||||
|     const checkoutInfo = await refHelper.getCheckoutInfo( |  | ||||||
|       git, |  | ||||||
|       'refs/tags/my-tag', |  | ||||||
|       commit |  | ||||||
|     ) |  | ||||||
|     expect(checkoutInfo.ref).toBe('refs/tags/my-tag') |  | ||||||
|     expect(checkoutInfo.startPoint).toBeFalsy() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getCheckoutInfo refs/', async () => { |  | ||||||
|     const checkoutInfo = await refHelper.getCheckoutInfo( |  | ||||||
|       git, |  | ||||||
|       'refs/gh/queue/main/pr-123', |  | ||||||
|       commit |  | ||||||
|     ) |  | ||||||
|     expect(checkoutInfo.ref).toBe(commit) |  | ||||||
|     expect(checkoutInfo.startPoint).toBeFalsy() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getCheckoutInfo refs/ without commit', async () => { |  | ||||||
|     const checkoutInfo = await refHelper.getCheckoutInfo( |  | ||||||
|       git, |  | ||||||
|       'refs/non-standard-ref', |  | ||||||
|       '' |  | ||||||
|     ) |  | ||||||
|     expect(checkoutInfo.ref).toBe('refs/non-standard-ref') |  | ||||||
|     expect(checkoutInfo.startPoint).toBeFalsy() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getCheckoutInfo unqualified branch only', async () => { |  | ||||||
|     git.branchExists = jest.fn(async (remote: boolean, pattern: string) => { |  | ||||||
|       return true |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|     const checkoutInfo = await refHelper.getCheckoutInfo(git, 'my/branch', '') |  | ||||||
| 
 |  | ||||||
|     expect(checkoutInfo.ref).toBe('my/branch') |  | ||||||
|     expect(checkoutInfo.startPoint).toBe('refs/remotes/origin/my/branch') |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getCheckoutInfo unqualified tag only', async () => { |  | ||||||
|     git.branchExists = jest.fn(async (remote: boolean, pattern: string) => { |  | ||||||
|       return false |  | ||||||
|     }) |  | ||||||
|     git.tagExists = jest.fn(async (pattern: string) => { |  | ||||||
|       return true |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|     const checkoutInfo = await refHelper.getCheckoutInfo(git, 'my-tag', '') |  | ||||||
| 
 |  | ||||||
|     expect(checkoutInfo.ref).toBe('refs/tags/my-tag') |  | ||||||
|     expect(checkoutInfo.startPoint).toBeFalsy() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getCheckoutInfo unqualified ref only, not a branch or tag', async () => { |  | ||||||
|     git.branchExists = jest.fn(async (remote: boolean, pattern: string) => { |  | ||||||
|       return false |  | ||||||
|     }) |  | ||||||
|     git.tagExists = jest.fn(async (pattern: string) => { |  | ||||||
|       return false |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|     try { |  | ||||||
|       await refHelper.getCheckoutInfo(git, 'my-ref', '') |  | ||||||
|       throw new Error('Should not reach here') |  | ||||||
|     } catch (err) { |  | ||||||
|       expect((err as any)?.message).toBe( |  | ||||||
|         "A branch or tag with the name 'my-ref' could not be found" |  | ||||||
|       ) |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getRefSpec requires ref or commit', async () => { |  | ||||||
|     assert.throws( |  | ||||||
|       () => refHelper.getRefSpec('', ''), |  | ||||||
|       /Args ref and commit cannot both be empty/ |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getRefSpec sha + refs/heads/', async () => { |  | ||||||
|     const refSpec = refHelper.getRefSpec('refs/heads/my/branch', commit) |  | ||||||
|     expect(refSpec.length).toBe(1) |  | ||||||
|     expect(refSpec[0]).toBe(`+${commit}:refs/remotes/origin/my/branch`) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getRefSpec sha + refs/pull/', async () => { |  | ||||||
|     const refSpec = refHelper.getRefSpec('refs/pull/123/merge', commit) |  | ||||||
|     expect(refSpec.length).toBe(1) |  | ||||||
|     expect(refSpec[0]).toBe(`+${commit}:refs/remotes/pull/123/merge`) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getRefSpec sha + refs/tags/', async () => { |  | ||||||
|     const refSpec = refHelper.getRefSpec('refs/tags/my-tag', commit) |  | ||||||
|     expect(refSpec.length).toBe(1) |  | ||||||
|     expect(refSpec[0]).toBe(`+${commit}:refs/tags/my-tag`) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getRefSpec sha only', async () => { |  | ||||||
|     const refSpec = refHelper.getRefSpec('', commit) |  | ||||||
|     expect(refSpec.length).toBe(1) |  | ||||||
|     expect(refSpec[0]).toBe(commit) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getRefSpec unqualified ref only', async () => { |  | ||||||
|     const refSpec = refHelper.getRefSpec('my-ref', '') |  | ||||||
|     expect(refSpec.length).toBe(2) |  | ||||||
|     expect(refSpec[0]).toBe('+refs/heads/my-ref*:refs/remotes/origin/my-ref*') |  | ||||||
|     expect(refSpec[1]).toBe('+refs/tags/my-ref*:refs/tags/my-ref*') |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getRefSpec refs/heads/ only', async () => { |  | ||||||
|     const refSpec = refHelper.getRefSpec('refs/heads/my/branch', '') |  | ||||||
|     expect(refSpec.length).toBe(1) |  | ||||||
|     expect(refSpec[0]).toBe( |  | ||||||
|       '+refs/heads/my/branch:refs/remotes/origin/my/branch' |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getRefSpec refs/pull/ only', async () => { |  | ||||||
|     const refSpec = refHelper.getRefSpec('refs/pull/123/merge', '') |  | ||||||
|     expect(refSpec.length).toBe(1) |  | ||||||
|     expect(refSpec[0]).toBe('+refs/pull/123/merge:refs/remotes/pull/123/merge') |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('getRefSpec refs/tags/ only', async () => { |  | ||||||
|     const refSpec = refHelper.getRefSpec('refs/tags/my-tag', '') |  | ||||||
|     expect(refSpec.length).toBe(1) |  | ||||||
|     expect(refSpec[0]).toBe('+refs/tags/my-tag:refs/tags/my-tag') |  | ||||||
|   }) |  | ||||||
| }) |  | ||||||
|  | @ -1,87 +0,0 @@ | ||||||
| import * as core from '@actions/core' |  | ||||||
| import {RetryHelper} from '../lib/retry-helper' |  | ||||||
| 
 |  | ||||||
| let info: string[] |  | ||||||
| let retryHelper: any |  | ||||||
| 
 |  | ||||||
| describe('retry-helper tests', () => { |  | ||||||
|   beforeAll(() => { |  | ||||||
|     // Mock @actions/core info()
 |  | ||||||
|     jest.spyOn(core, 'info').mockImplementation((message: string) => { |  | ||||||
|       info.push(message) |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|     retryHelper = new RetryHelper(3, 0, 0) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   beforeEach(() => { |  | ||||||
|     // Reset info
 |  | ||||||
|     info = [] |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   afterAll(() => { |  | ||||||
|     // Restore
 |  | ||||||
|     jest.restoreAllMocks() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('first attempt succeeds', async () => { |  | ||||||
|     const actual = await retryHelper.execute(async () => { |  | ||||||
|       return 'some result' |  | ||||||
|     }) |  | ||||||
|     expect(actual).toBe('some result') |  | ||||||
|     expect(info).toHaveLength(0) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('second attempt succeeds', async () => { |  | ||||||
|     let attempts = 0 |  | ||||||
|     const actual = await retryHelper.execute(() => { |  | ||||||
|       if (++attempts == 1) { |  | ||||||
|         throw new Error('some error') |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       return Promise.resolve('some result') |  | ||||||
|     }) |  | ||||||
|     expect(attempts).toBe(2) |  | ||||||
|     expect(actual).toBe('some result') |  | ||||||
|     expect(info).toHaveLength(2) |  | ||||||
|     expect(info[0]).toBe('some error') |  | ||||||
|     expect(info[1]).toMatch(/Waiting .+ seconds before trying again/) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('third attempt succeeds', async () => { |  | ||||||
|     let attempts = 0 |  | ||||||
|     const actual = await retryHelper.execute(() => { |  | ||||||
|       if (++attempts < 3) { |  | ||||||
|         throw new Error(`some error ${attempts}`) |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       return Promise.resolve('some result') |  | ||||||
|     }) |  | ||||||
|     expect(attempts).toBe(3) |  | ||||||
|     expect(actual).toBe('some result') |  | ||||||
|     expect(info).toHaveLength(4) |  | ||||||
|     expect(info[0]).toBe('some error 1') |  | ||||||
|     expect(info[1]).toMatch(/Waiting .+ seconds before trying again/) |  | ||||||
|     expect(info[2]).toBe('some error 2') |  | ||||||
|     expect(info[3]).toMatch(/Waiting .+ seconds before trying again/) |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('all attempts fail succeeds', async () => { |  | ||||||
|     let attempts = 0 |  | ||||||
|     let error: Error = null as unknown as Error |  | ||||||
|     try { |  | ||||||
|       await retryHelper.execute(() => { |  | ||||||
|         throw new Error(`some error ${++attempts}`) |  | ||||||
|       }) |  | ||||||
|     } catch (err) { |  | ||||||
|       error = err as Error |  | ||||||
|     } |  | ||||||
|     expect(error.message).toBe('some error 3') |  | ||||||
|     expect(attempts).toBe(3) |  | ||||||
|     expect(info).toHaveLength(4) |  | ||||||
|     expect(info[0]).toBe('some error 1') |  | ||||||
|     expect(info[1]).toMatch(/Waiting .+ seconds before trying again/) |  | ||||||
|     expect(info[2]).toBe('some error 2') |  | ||||||
|     expect(info[3]).toMatch(/Waiting .+ seconds before trying again/) |  | ||||||
|   }) |  | ||||||
| }) |  | ||||||
|  | @ -1,92 +0,0 @@ | ||||||
| import * as urlHelper from '../src/url-helper' |  | ||||||
| 
 |  | ||||||
| describe('getServerUrl tests', () => { |  | ||||||
|   it('basics', async () => { |  | ||||||
|     // Note that URL::toString will append a trailing / when passed just a domain name ...
 |  | ||||||
|     expect(urlHelper.getServerUrl().toString()).toBe('https://github.com/') |  | ||||||
|     expect(urlHelper.getServerUrl(' ').toString()).toBe('https://github.com/') |  | ||||||
|     expect(urlHelper.getServerUrl('   ').toString()).toBe('https://github.com/') |  | ||||||
|     expect(urlHelper.getServerUrl('http://contoso.com').toString()).toBe( |  | ||||||
|       'http://contoso.com/' |  | ||||||
|     ) |  | ||||||
|     expect(urlHelper.getServerUrl('https://contoso.com').toString()).toBe( |  | ||||||
|       'https://contoso.com/' |  | ||||||
|     ) |  | ||||||
|     expect(urlHelper.getServerUrl('https://contoso.com/').toString()).toBe( |  | ||||||
|       'https://contoso.com/' |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     // ... but can't make that same assumption when passed an URL that includes some deeper path.
 |  | ||||||
|     expect(urlHelper.getServerUrl('https://contoso.com/a/b').toString()).toBe( |  | ||||||
|       'https://contoso.com/a/b' |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
| }) |  | ||||||
| 
 |  | ||||||
| describe('isGhes tests', () => { |  | ||||||
|   const pristineEnv = process.env |  | ||||||
| 
 |  | ||||||
|   beforeEach(() => { |  | ||||||
|     jest.resetModules() |  | ||||||
|     process.env = {...pristineEnv} |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   afterAll(() => { |  | ||||||
|     process.env = pristineEnv |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('basics', async () => { |  | ||||||
|     delete process.env['GITHUB_SERVER_URL'] |  | ||||||
|     expect(urlHelper.isGhes()).toBeFalsy() |  | ||||||
|     expect(urlHelper.isGhes('https://github.com')).toBeFalsy() |  | ||||||
|     expect(urlHelper.isGhes('https://contoso.ghe.com')).toBeFalsy() |  | ||||||
|     expect(urlHelper.isGhes('https://test.github.localhost')).toBeFalsy() |  | ||||||
|     expect(urlHelper.isGhes('https://src.onpremise.fabrikam.com')).toBeTruthy() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('returns false when the GITHUB_SERVER_URL environment variable is not defined', async () => { |  | ||||||
|     delete process.env['GITHUB_SERVER_URL'] |  | ||||||
|     expect(urlHelper.isGhes()).toBeFalsy() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('returns false when the GITHUB_SERVER_URL environment variable is set to github.com', async () => { |  | ||||||
|     process.env['GITHUB_SERVER_URL'] = 'https://github.com' |  | ||||||
|     expect(urlHelper.isGhes()).toBeFalsy() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('returns false when the GITHUB_SERVER_URL environment variable is set to a GitHub Enterprise Cloud-style URL', async () => { |  | ||||||
|     process.env['GITHUB_SERVER_URL'] = 'https://contoso.ghe.com' |  | ||||||
|     expect(urlHelper.isGhes()).toBeFalsy() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('returns false when the GITHUB_SERVER_URL environment variable has a .localhost suffix', async () => { |  | ||||||
|     process.env['GITHUB_SERVER_URL'] = 'https://mock-github.localhost' |  | ||||||
|     expect(urlHelper.isGhes()).toBeFalsy() |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
|   it('returns true when the GITHUB_SERVER_URL environment variable is set to some other URL', async () => { |  | ||||||
|     process.env['GITHUB_SERVER_URL'] = 'https://src.onpremise.fabrikam.com' |  | ||||||
|     expect(urlHelper.isGhes()).toBeTruthy() |  | ||||||
|   }) |  | ||||||
| }) |  | ||||||
| 
 |  | ||||||
| describe('getServerApiUrl tests', () => { |  | ||||||
|   it('basics', async () => { |  | ||||||
|     expect(urlHelper.getServerApiUrl()).toBe('https://api.github.com') |  | ||||||
|     expect(urlHelper.getServerApiUrl('https://github.com')).toBe( |  | ||||||
|       'https://api.github.com' |  | ||||||
|     ) |  | ||||||
|     expect(urlHelper.getServerApiUrl('https://GitHub.com')).toBe( |  | ||||||
|       'https://api.github.com' |  | ||||||
|     ) |  | ||||||
|     expect(urlHelper.getServerApiUrl('https://contoso.ghe.com')).toBe( |  | ||||||
|       'https://api.contoso.ghe.com' |  | ||||||
|     ) |  | ||||||
|     expect(urlHelper.getServerApiUrl('https://fabrikam.GHE.COM')).toBe( |  | ||||||
|       'https://api.fabrikam.ghe.com' |  | ||||||
|     ) |  | ||||||
|     expect( |  | ||||||
|       urlHelper.getServerApiUrl('https://src.onpremise.fabrikam.com') |  | ||||||
|     ).toBe('https://src.onpremise.fabrikam.com/api/v3') |  | ||||||
|   }) |  | ||||||
| }) |  | ||||||
|  | @ -1,38 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| if [ ! -f "./basic/basic-file.txt" ]; then |  | ||||||
|     echo "Expected basic file does not exist" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| if [ "$1" = "--archive" ]; then |  | ||||||
|   # Verify no .git folder |  | ||||||
|   if [ -d "./basic/.git" ]; then |  | ||||||
|     echo "Did not expect ./basic/.git folder to exist" |  | ||||||
|     exit 1 |  | ||||||
|   fi |  | ||||||
| else |  | ||||||
|   # Verify .git folder |  | ||||||
|   if [ ! -d "./basic/.git" ]; then |  | ||||||
|     echo "Expected ./basic/.git folder to exist" |  | ||||||
|     exit 1 |  | ||||||
|   fi |  | ||||||
| 
 |  | ||||||
|   # Verify that sparse-checkout is disabled. |  | ||||||
|   SPARSE_CHECKOUT_ENABLED=$(git -C ./basic config --local --get-all core.sparseCheckout) |  | ||||||
|   if [ "$SPARSE_CHECKOUT_ENABLED" != "" ]; then |  | ||||||
|     echo "Expected sparse-checkout to be disabled (discovered: $SPARSE_CHECKOUT_ENABLED)" |  | ||||||
|     exit 1 |  | ||||||
|   fi |  | ||||||
| 
 |  | ||||||
|   # Verify git configuration shows worktreeConfig is effectively disabled |  | ||||||
|   WORKTREE_CONFIG_ENABLED=$(git -C ./basic config --local --get-all extensions.worktreeConfig) |  | ||||||
|   if [[ "$WORKTREE_CONFIG_ENABLED" != "" ]]; then |  | ||||||
|     echo "Expected extensions.worktreeConfig (boolean) to be disabled in git config.  This could be an artifact of sparse checkout functionality." |  | ||||||
|     exit 1 |  | ||||||
|   fi |  | ||||||
| 
 |  | ||||||
|   # Verify auth token |  | ||||||
|   cd basic |  | ||||||
|   git fetch --no-tags --depth=1 origin +refs/heads/main:refs/remotes/origin/main |  | ||||||
| fi |  | ||||||
|  | @ -1,13 +0,0 @@ | ||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| if [[ "$(git -C ./basic status --porcelain)" != "" ]]; then |  | ||||||
|     echo ---------------------------------------- |  | ||||||
|     echo git status |  | ||||||
|     echo ---------------------------------------- |  | ||||||
|     git status |  | ||||||
|     echo ---------------------------------------- |  | ||||||
|     echo git diff |  | ||||||
|     echo ---------------------------------------- |  | ||||||
|     git diff |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
|  | @ -1,16 +0,0 @@ | ||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| # Verify .git folder |  | ||||||
| if [ ! -d "./fetch-filter/.git" ]; then |  | ||||||
|   echo "Expected ./fetch-filter/.git folder to exist" |  | ||||||
|   exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| # Verify .git/config contains partialclonefilter |  | ||||||
| 
 |  | ||||||
| CLONE_FILTER=$(git -C fetch-filter config --local --get remote.origin.partialclonefilter) |  | ||||||
| 
 |  | ||||||
| if [ "$CLONE_FILTER" != "blob:none" ]; then |  | ||||||
|   echo "Expected ./fetch-filter/.git/config to have 'remote.origin.partialclonefilter' set to 'blob:none'" |  | ||||||
|   exit 1 |  | ||||||
| fi |  | ||||||
|  | @ -1,11 +0,0 @@ | ||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| if [ ! -f "./lfs/regular-file.txt" ]; then |  | ||||||
|     echo "Expected regular file does not exist" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| if [ ! -f "./lfs/lfs-file.bin" ]; then |  | ||||||
|     echo "Expected lfs file does not exist" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
|  | @ -1,17 +0,0 @@ | ||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| if [[ "$(git status --porcelain)" != "" ]]; then |  | ||||||
|     echo ---------------------------------------- |  | ||||||
|     echo git status |  | ||||||
|     echo ---------------------------------------- |  | ||||||
|     git status |  | ||||||
|     echo ---------------------------------------- |  | ||||||
|     echo git diff |  | ||||||
|     echo ---------------------------------------- |  | ||||||
|     git diff |  | ||||||
|     echo ---------------------------------------- |  | ||||||
|     echo Troubleshooting |  | ||||||
|     echo ---------------------------------------- |  | ||||||
|     echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && npm ci && npm run format && npm run build" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
|  | @ -1,11 +0,0 @@ | ||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| if [ ! -f "./side-by-side-1/side-by-side-test-file-1.txt" ]; then |  | ||||||
|     echo "Expected file 1 does not exist" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| if [ ! -f "./side-by-side-2/side-by-side-test-file-2.txt" ]; then |  | ||||||
|     echo "Expected file 2 does not exist" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
|  | @ -1,51 +0,0 @@ | ||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| # Verify .git folder |  | ||||||
| if [ ! -d "./sparse-checkout-non-cone-mode/.git" ]; then |  | ||||||
|   echo "Expected ./sparse-checkout-non-cone-mode/.git folder to exist" |  | ||||||
|   exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| # Verify sparse-checkout (non-cone-mode) |  | ||||||
| cd sparse-checkout-non-cone-mode |  | ||||||
| 
 |  | ||||||
| ENABLED=$(git config --local --get-all core.sparseCheckout) |  | ||||||
| 
 |  | ||||||
| if [ "$?" != "0" ]; then |  | ||||||
|     echo "Failed to verify that sparse-checkout is enabled" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| # Check that sparse-checkout is enabled |  | ||||||
| if [ "$ENABLED" != "true" ]; then |  | ||||||
|   echo "Expected sparse-checkout to be enabled (is: $ENABLED)" |  | ||||||
|   exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| SPARSE_CHECKOUT_FILE=$(git rev-parse --git-path info/sparse-checkout) |  | ||||||
| 
 |  | ||||||
| if [ "$?" != "0" ]; then |  | ||||||
|     echo "Failed to validate sparse-checkout" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| # Check that sparse-checkout list is not empty |  | ||||||
| if [ ! -f "$SPARSE_CHECKOUT_FILE" ]; then |  | ||||||
|   echo "Expected sparse-checkout file to exist" |  | ||||||
|   exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| # Check that all folders from sparse-checkout exists |  | ||||||
| for pattern in $(cat "$SPARSE_CHECKOUT_FILE") |  | ||||||
| do |  | ||||||
|   if [ ! -d "${pattern#/}" ]; then |  | ||||||
|     echo "Expected directory '${pattern#/}' to exist" |  | ||||||
|     exit 1 |  | ||||||
|   fi |  | ||||||
| done |  | ||||||
| 
 |  | ||||||
| # Verify that the root directory is not checked out |  | ||||||
| if [ -f README.md ]; then |  | ||||||
|   echo "Expected top-level files not to exist" |  | ||||||
|   exit 1 |  | ||||||
| fi |  | ||||||
|  | @ -1,63 +0,0 @@ | ||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| # Verify .git folder |  | ||||||
| if [ ! -d "./sparse-checkout/.git" ]; then |  | ||||||
|   echo "Expected ./sparse-checkout/.git folder to exist" |  | ||||||
|   exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| # Verify sparse-checkout |  | ||||||
| cd sparse-checkout |  | ||||||
| 
 |  | ||||||
| SPARSE=$(git sparse-checkout list) |  | ||||||
| 
 |  | ||||||
| if [ "$?" != "0" ]; then |  | ||||||
|     echo "Failed to validate sparse-checkout" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| # Check that sparse-checkout list is not empty |  | ||||||
| if [ -z "$SPARSE" ]; then |  | ||||||
|   echo "Expected sparse-checkout list to not be empty" |  | ||||||
|   exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| # Check that all folders of the sparse checkout exist |  | ||||||
| for pattern in $SPARSE |  | ||||||
| do |  | ||||||
|   if [ ! -d "$pattern" ]; then |  | ||||||
|     echo "Expected directory '$pattern' to exist" |  | ||||||
|     exit 1 |  | ||||||
|   fi |  | ||||||
| done |  | ||||||
| 
 |  | ||||||
| checkSparse () { |  | ||||||
|   if [ ! -d "./$1" ]; then |  | ||||||
|     echo "Expected directory '$1' to exist" |  | ||||||
|     exit 1 |  | ||||||
|   fi |  | ||||||
| 
 |  | ||||||
|   for file in $(git ls-tree -r --name-only HEAD $1) |  | ||||||
|   do |  | ||||||
|     if [ ! -f "$file" ]; then |  | ||||||
|       echo "Expected file '$file' to exist" |  | ||||||
|       exit 1 |  | ||||||
|     fi |  | ||||||
|   done |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| # Check that all folders and their children have been checked out |  | ||||||
| checkSparse __test__ |  | ||||||
| checkSparse .github |  | ||||||
| checkSparse dist |  | ||||||
| 
 |  | ||||||
| # Check that only sparse-checkout folders have been checked out |  | ||||||
| for pattern in $(git ls-tree --name-only HEAD) |  | ||||||
| do |  | ||||||
|   if [ -d "$pattern" ]; then |  | ||||||
|     if [[ "$pattern" != "__test__" && "$pattern" != ".github" && "$pattern" != "dist" ]]; then |  | ||||||
|       echo "Expected directory '$pattern' to not exist" |  | ||||||
|       exit 1 |  | ||||||
|     fi |  | ||||||
|   fi |  | ||||||
| done |  | ||||||
|  | @ -1,11 +0,0 @@ | ||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| if [ ! -f "./submodules-false/regular-file.txt" ]; then |  | ||||||
|     echo "Expected regular file does not exist" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| if [ -f "./submodules-false/submodule-level-1/submodule-file.txt" ]; then |  | ||||||
|     echo "Unexpected submodule file exists" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
|  | @ -1,26 +0,0 @@ | ||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| if [ ! -f "./submodules-recursive/regular-file.txt" ]; then |  | ||||||
|     echo "Expected regular file does not exist" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| if [ ! -f "./submodules-recursive/submodule-level-1/submodule-file.txt" ]; then |  | ||||||
|     echo "Expected submodule file does not exist" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| if [ ! -f "./submodules-recursive/submodule-level-1/submodule-level-2/nested-submodule-file.txt" ]; then |  | ||||||
|     echo "Expected nested submodule file does not exists" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| echo "Testing persisted credential" |  | ||||||
| pushd ./submodules-recursive/submodule-level-1/submodule-level-2 |  | ||||||
| git config --local --name-only --get-regexp http.+extraheader && git fetch |  | ||||||
| if [ "$?" != "0" ]; then |  | ||||||
|     echo "Failed to validate persisted credential" |  | ||||||
|     popd |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| popd |  | ||||||
|  | @ -1,26 +0,0 @@ | ||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| if [ ! -f "./submodules-true/regular-file.txt" ]; then |  | ||||||
|     echo "Expected regular file does not exist" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| if [ ! -f "./submodules-true/submodule-level-1/submodule-file.txt" ]; then |  | ||||||
|     echo "Expected submodule file does not exist" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| if [ -f "./submodules-true/submodule-level-1/submodule-level-2/nested-submodule-file.txt" ]; then |  | ||||||
|     echo "Unexpected nested submodule file exists" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| echo "Testing persisted credential" |  | ||||||
| pushd ./submodules-true/submodule-level-1 |  | ||||||
| git config --local --name-only --get-regexp http.+extraheader && git fetch |  | ||||||
| if [ "$?" != "0" ]; then |  | ||||||
|     echo "Failed to validate persisted credential" |  | ||||||
|     popd |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| popd |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 andreanadr
						andreanadr