mirror of
				https://github.com/actions/checkout.git
				synced 2025-10-31 18:18: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