mirror of
				https://github.com/actions/checkout.git
				synced 2025-10-31 18:18:37 +08:00 
			
		
		
		
	Implement branch list using callbacks from exec function
This commit is contained in:
		
							parent
							
								
									755da8c3cf
								
							
						
					
					
						commit
						3cd5238e16
					
				
							
								
								
									
										80
									
								
								__test__/git-command-manager.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								__test__/git-command-manager.test.ts
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,80 @@ | |||
| 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 | ||||
|     git = await commandManager.createCommandManager(workingDirectory, lfs) | ||||
| 
 | ||||
|     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 | ||||
|     git = await commandManager.createCommandManager(workingDirectory, lfs) | ||||
| 
 | ||||
|     let branches = await git.branchList(false) | ||||
| 
 | ||||
|     expect(branches).toHaveLength(1) | ||||
|     expect(branches.sort()).toEqual(['foo'].sort()) | ||||
|   }) | ||||
| }) | ||||
							
								
								
									
										68
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										68
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							|  | @ -7441,8 +7441,10 @@ class GitCommandManager { | |||
|             const result = []; | ||||
|             // Note, this implementation uses "rev-parse --symbolic-full-name" because the output from
 | ||||
|             // "branch --list" is more difficult when in a detached HEAD state.
 | ||||
|             // Note, this implementation uses "rev-parse --symbolic-full-name" because there is a bug
 | ||||
|             // in Git 2.18 that causes "rev-parse --symbolic" to output symbolic full names.
 | ||||
|             // TODO(https://github.com/actions/checkout/issues/786): this implementation uses
 | ||||
|             // "rev-parse --symbolic-full-name" because there is a bug
 | ||||
|             // in Git 2.18 that causes "rev-parse --symbolic" to output symbolic full names. When
 | ||||
|             // 2.18 is no longer supported, we can switch back to --symbolic.
 | ||||
|             const args = ['rev-parse', '--symbolic-full-name']; | ||||
|             if (remote) { | ||||
|                 args.push('--remotes=origin'); | ||||
|  | @ -7450,18 +7452,42 @@ class GitCommandManager { | |||
|             else { | ||||
|                 args.push('--branches'); | ||||
|             } | ||||
|             const output = yield this.execGit(args); | ||||
|             for (let branch of output.stdout.trim().split('\n')) { | ||||
|                 branch = branch.trim(); | ||||
|                 if (branch) { | ||||
|                     if (branch.startsWith('refs/heads/')) { | ||||
|                         branch = branch.substr('refs/heads/'.length); | ||||
|                     } | ||||
|                     else if (branch.startsWith('refs/remotes/')) { | ||||
|                         branch = branch.substr('refs/remotes/'.length); | ||||
|                     } | ||||
|                     result.push(branch); | ||||
|             const stderr = []; | ||||
|             const errline = []; | ||||
|             const stdout = []; | ||||
|             const stdline = []; | ||||
|             const listeners = { | ||||
|                 stderr: (data) => { | ||||
|                     stderr.push(data.toString()); | ||||
|                 }, | ||||
|                 errline: (data) => { | ||||
|                     errline.push(data.toString()); | ||||
|                 }, | ||||
|                 stdout: (data) => { | ||||
|                     stdout.push(data.toString()); | ||||
|                 }, | ||||
|                 stdline: (data) => { | ||||
|                     stdline.push(data.toString()); | ||||
|                 } | ||||
|             }; | ||||
|             // Suppress the output in order to avoid flooding annotations with innocuous errors.
 | ||||
|             yield this.execGit(args, false, true, listeners); | ||||
|             core.debug(`stderr callback is: ${stderr}`); | ||||
|             core.debug(`errline callback is: ${errline}`); | ||||
|             core.debug(`stdout callback is: ${stdout}`); | ||||
|             core.debug(`stdline callback is: ${stdline}`); | ||||
|             for (let branch of stdline) { | ||||
|                 branch = branch.trim(); | ||||
|                 if (!branch) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 if (branch.startsWith('refs/heads/')) { | ||||
|                     branch = branch.substring('refs/heads/'.length); | ||||
|                 } | ||||
|                 else if (branch.startsWith('refs/remotes/')) { | ||||
|                     branch = branch.substring('refs/remotes/'.length); | ||||
|                 } | ||||
|                 result.push(branch); | ||||
|             } | ||||
|             return result; | ||||
|         }); | ||||
|  | @ -7712,7 +7738,7 @@ class GitCommandManager { | |||
|             return result; | ||||
|         }); | ||||
|     } | ||||
|     execGit(args, allowAllExitCodes = false, silent = false) { | ||||
|     execGit(args, allowAllExitCodes = false, silent = false, customListeners = {}) { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             fshelper.directoryExistsSync(this.workingDirectory, true); | ||||
|             const result = new GitOutput(); | ||||
|  | @ -7723,20 +7749,24 @@ class GitCommandManager { | |||
|             for (const key of Object.keys(this.gitEnv)) { | ||||
|                 env[key] = this.gitEnv[key]; | ||||
|             } | ||||
|             const defaultListener = { | ||||
|                 stdout: (data) => { | ||||
|                     stdout.push(data.toString()); | ||||
|                 } | ||||
|             }; | ||||
|             const mergedListeners = Object.assign(Object.assign({}, defaultListener), customListeners); | ||||
|             const stdout = []; | ||||
|             const options = { | ||||
|                 cwd: this.workingDirectory, | ||||
|                 env, | ||||
|                 silent, | ||||
|                 ignoreReturnCode: allowAllExitCodes, | ||||
|                 listeners: { | ||||
|                     stdout: (data) => { | ||||
|                         stdout.push(data.toString()); | ||||
|                     } | ||||
|                 } | ||||
|                 listeners: mergedListeners | ||||
|             }; | ||||
|             result.exitCode = yield exec.exec(`"${this.gitPath}"`, args, options); | ||||
|             result.stdout = stdout.join(''); | ||||
|             core.debug(result.exitCode.toString()); | ||||
|             core.debug(result.stdout); | ||||
|             return result; | ||||
|         }); | ||||
|     } | ||||
|  |  | |||
|  | @ -94,8 +94,11 @@ class GitCommandManager { | |||
| 
 | ||||
|     // Note, this implementation uses "rev-parse --symbolic-full-name" because the output from
 | ||||
|     // "branch --list" is more difficult when in a detached HEAD state.
 | ||||
|     // Note, this implementation uses "rev-parse --symbolic-full-name" because there is a bug
 | ||||
|     // in Git 2.18 that causes "rev-parse --symbolic" to output symbolic full names.
 | ||||
| 
 | ||||
|     // TODO(https://github.com/actions/checkout/issues/786): this implementation uses
 | ||||
|     // "rev-parse --symbolic-full-name" because there is a bug
 | ||||
|     // in Git 2.18 that causes "rev-parse --symbolic" to output symbolic full names. When
 | ||||
|     // 2.18 is no longer supported, we can switch back to --symbolic.
 | ||||
| 
 | ||||
|     const args = ['rev-parse', '--symbolic-full-name'] | ||||
|     if (remote) { | ||||
|  | @ -104,21 +107,49 @@ class GitCommandManager { | |||
|       args.push('--branches') | ||||
|     } | ||||
| 
 | ||||
|     const output = await this.execGit(args) | ||||
|     const stderr: string[] = [] | ||||
|     const errline: string[] = [] | ||||
|     const stdout: string[] = [] | ||||
|     const stdline: string[] = [] | ||||
| 
 | ||||
|     for (let branch of output.stdout.trim().split('\n')) { | ||||
|       branch = branch.trim() | ||||
|       if (branch) { | ||||
|         if (branch.startsWith('refs/heads/')) { | ||||
|           branch = branch.substr('refs/heads/'.length) | ||||
|         } else if (branch.startsWith('refs/remotes/')) { | ||||
|           branch = branch.substr('refs/remotes/'.length) | ||||
|         } | ||||
| 
 | ||||
|         result.push(branch) | ||||
|     const listeners = { | ||||
|       stderr: (data: Buffer) => { | ||||
|         stderr.push(data.toString()) | ||||
|       }, | ||||
|       errline: (data: Buffer) => { | ||||
|         errline.push(data.toString()) | ||||
|       }, | ||||
|       stdout: (data: Buffer) => { | ||||
|         stdout.push(data.toString()) | ||||
|       }, | ||||
|       stdline: (data: Buffer) => { | ||||
|         stdline.push(data.toString()) | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     // Suppress the output in order to avoid flooding annotations with innocuous errors.
 | ||||
|     await this.execGit(args, false, true, listeners) | ||||
| 
 | ||||
|     core.debug(`stderr callback is: ${stderr}`) | ||||
|     core.debug(`errline callback is: ${errline}`) | ||||
|     core.debug(`stdout callback is: ${stdout}`) | ||||
|     core.debug(`stdline callback is: ${stdline}`) | ||||
| 
 | ||||
|     for (let branch of stdline) { | ||||
|       branch = branch.trim() | ||||
|       if (!branch) { | ||||
|         continue | ||||
|       } | ||||
| 
 | ||||
|       if (branch.startsWith('refs/heads/')) { | ||||
|         branch = branch.substring('refs/heads/'.length) | ||||
|       } else if (branch.startsWith('refs/remotes/')) { | ||||
|         branch = branch.substring('refs/remotes/'.length) | ||||
|       } | ||||
| 
 | ||||
|       result.push(branch) | ||||
|     } | ||||
| 
 | ||||
|     return result | ||||
|   } | ||||
| 
 | ||||
|  | @ -395,7 +426,8 @@ class GitCommandManager { | |||
|   private async execGit( | ||||
|     args: string[], | ||||
|     allowAllExitCodes = false, | ||||
|     silent = false | ||||
|     silent = false, | ||||
|     customListeners = {} | ||||
|   ): Promise<GitOutput> { | ||||
|     fshelper.directoryExistsSync(this.workingDirectory, true) | ||||
| 
 | ||||
|  | @ -409,22 +441,29 @@ class GitCommandManager { | |||
|       env[key] = this.gitEnv[key] | ||||
|     } | ||||
| 
 | ||||
|     const stdout: string[] = [] | ||||
|     const defaultListener = { | ||||
|       stdout: (data: Buffer) => { | ||||
|         stdout.push(data.toString()) | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     const mergedListeners = {...defaultListener, ...customListeners} | ||||
| 
 | ||||
|     const stdout: string[] = [] | ||||
|     const options = { | ||||
|       cwd: this.workingDirectory, | ||||
|       env, | ||||
|       silent, | ||||
|       ignoreReturnCode: allowAllExitCodes, | ||||
|       listeners: { | ||||
|         stdout: (data: Buffer) => { | ||||
|           stdout.push(data.toString()) | ||||
|         } | ||||
|       } | ||||
|       listeners: mergedListeners | ||||
|     } | ||||
| 
 | ||||
|     result.exitCode = await exec.exec(`"${this.gitPath}"`, args, options) | ||||
|     result.stdout = stdout.join('') | ||||
| 
 | ||||
|     core.debug(result.exitCode.toString()) | ||||
|     core.debug(result.stdout) | ||||
| 
 | ||||
|     return result | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Cory Miller
						Cory Miller