mirror of
				https://github.com/actions/checkout.git
				synced 2025-10-31 07:30:32 +00:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			users/eric
			...
			revert-56-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | d8d55467a3 | 
| @@ -1,3 +0,0 @@ | |||||||
| dist/ |  | ||||||
| lib/ |  | ||||||
| node_modules/ |  | ||||||
| @@ -1,58 +0,0 @@ | |||||||
| { |  | ||||||
|   "plugins": ["jest", "@typescript-eslint"], |  | ||||||
|   "extends": ["plugin:github/es6"], |  | ||||||
|   "parser": "@typescript-eslint/parser", |  | ||||||
|   "parserOptions": { |  | ||||||
|     "ecmaVersion": 9, |  | ||||||
|     "sourceType": "module", |  | ||||||
|     "project": "./tsconfig.json" |  | ||||||
|   }, |  | ||||||
|   "rules": { |  | ||||||
|     "eslint-comments/no-use": "off", |  | ||||||
|     "import/no-namespace": "off", |  | ||||||
|     "no-unused-vars": "off", |  | ||||||
|     "@typescript-eslint/no-unused-vars": "error", |  | ||||||
|     "@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}], |  | ||||||
|     "@typescript-eslint/no-require-imports": "error", |  | ||||||
|     "@typescript-eslint/array-type": "error", |  | ||||||
|     "@typescript-eslint/await-thenable": "error", |  | ||||||
|     "@typescript-eslint/ban-ts-ignore": "error", |  | ||||||
|     "camelcase": "off", |  | ||||||
|     "@typescript-eslint/camelcase": "error", |  | ||||||
|     "@typescript-eslint/class-name-casing": "error", |  | ||||||
|     "@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}], |  | ||||||
|     "@typescript-eslint/func-call-spacing": ["error", "never"], |  | ||||||
|     "@typescript-eslint/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"], |  | ||||||
|     "@typescript-eslint/no-array-constructor": "error", |  | ||||||
|     "@typescript-eslint/no-empty-interface": "error", |  | ||||||
|     "@typescript-eslint/no-explicit-any": "error", |  | ||||||
|     "@typescript-eslint/no-extraneous-class": "error", |  | ||||||
|     "@typescript-eslint/no-for-in-array": "error", |  | ||||||
|     "@typescript-eslint/no-inferrable-types": "error", |  | ||||||
|     "@typescript-eslint/no-misused-new": "error", |  | ||||||
|     "@typescript-eslint/no-namespace": "error", |  | ||||||
|     "@typescript-eslint/no-non-null-assertion": "warn", |  | ||||||
|     "@typescript-eslint/no-object-literal-type-assertion": "error", |  | ||||||
|     "@typescript-eslint/no-unnecessary-qualifier": "error", |  | ||||||
|     "@typescript-eslint/no-unnecessary-type-assertion": "error", |  | ||||||
|     "@typescript-eslint/no-useless-constructor": "error", |  | ||||||
|     "@typescript-eslint/no-var-requires": "error", |  | ||||||
|     "@typescript-eslint/prefer-for-of": "warn", |  | ||||||
|     "@typescript-eslint/prefer-function-type": "warn", |  | ||||||
|     "@typescript-eslint/prefer-includes": "error", |  | ||||||
|     "@typescript-eslint/prefer-interface": "error", |  | ||||||
|     "@typescript-eslint/prefer-string-starts-ends-with": "error", |  | ||||||
|     "@typescript-eslint/promise-function-async": "error", |  | ||||||
|     "@typescript-eslint/require-array-sort-compare": "error", |  | ||||||
|     "@typescript-eslint/restrict-plus-operands": "error", |  | ||||||
|     "semi": "off", |  | ||||||
|     "@typescript-eslint/semi": ["error", "never"], |  | ||||||
|     "@typescript-eslint/type-annotation-spacing": "error", |  | ||||||
|     "@typescript-eslint/unbound-method": "error" |  | ||||||
|   }, |  | ||||||
|   "env": { |  | ||||||
|     "node": true, |  | ||||||
|     "es6": true, |  | ||||||
|     "jest/globals": true |  | ||||||
|   } |  | ||||||
| } |  | ||||||
							
								
								
									
										83
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										83
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,83 +0,0 @@ | |||||||
| name: Build and Test |  | ||||||
|  |  | ||||||
| on: |  | ||||||
|   pull_request: |  | ||||||
|   push: |  | ||||||
|     branches: |  | ||||||
|       - master |  | ||||||
|       - releases/* |  | ||||||
|  |  | ||||||
| jobs: |  | ||||||
|   build: |  | ||||||
|     runs-on: ubuntu-latest |  | ||||||
|     steps: |  | ||||||
|       - uses: actions/checkout@v1 # todo: switch to v2 |  | ||||||
|       - run: npm ci |  | ||||||
|       - run: npm run build |  | ||||||
|       - run: npm run format-check |  | ||||||
|       - run: npm run lint |  | ||||||
|       - run: npm run pack |  | ||||||
|       - run: npm run gendocs |  | ||||||
|       - name: Verify no unstaged changes |  | ||||||
|         run: __test__/verify-no-unstaged-changes.sh |  | ||||||
|  |  | ||||||
|   test: |  | ||||||
|     strategy: |  | ||||||
|       matrix: |  | ||||||
|         runs-on: [ubuntu-latest, macos-latest, windows-latest] |  | ||||||
|     runs-on: ${{ matrix.runs-on }} |  | ||||||
|  |  | ||||||
|     steps: |  | ||||||
|       # Clone this repo |  | ||||||
|       - name: Checkout |  | ||||||
|         uses: actions/checkout@v1 # todo: switch to V2 |  | ||||||
|  |  | ||||||
|       # Basic checkout |  | ||||||
|       - name: Basic checkout |  | ||||||
|         uses: ./ |  | ||||||
|         with: |  | ||||||
|           ref: test-data/v2/basic |  | ||||||
|           path: basic |  | ||||||
|       - name: Verify basic |  | ||||||
|         shell: bash |  | ||||||
|         run: __test__/verify-basic.sh |  | ||||||
|  |  | ||||||
|       # Clean |  | ||||||
|       - name: Modify work tree |  | ||||||
|         shell: bash |  | ||||||
|         run: __test__/modify-work-tree.sh |  | ||||||
|       - name: Clean checkout |  | ||||||
|         uses: ./ |  | ||||||
|         with: |  | ||||||
|           ref: test-data/v2/basic |  | ||||||
|           path: basic |  | ||||||
|       - name: Verify clean |  | ||||||
|         shell: bash |  | ||||||
|         run: __test__/verify-clean.sh |  | ||||||
|  |  | ||||||
|       # Side by side |  | ||||||
|       - name: Side by side checkout 1 |  | ||||||
|         uses: ./ |  | ||||||
|         with: |  | ||||||
|           ref: test-data/v2/side-by-side-1 |  | ||||||
|           path: side-by-side-1 |  | ||||||
|       - name: Side by side checkout 2 |  | ||||||
|         uses: ./ |  | ||||||
|         with: |  | ||||||
|           ref: test-data/v2/side-by-side-2 |  | ||||||
|           path: side-by-side-2 |  | ||||||
|       - name: Verify side by side |  | ||||||
|         shell: bash |  | ||||||
|         run: __test__/verify-side-by-side.sh |  | ||||||
|  |  | ||||||
|       # LFS |  | ||||||
|       - name: LFS checkout |  | ||||||
|         uses: ./ |  | ||||||
|         with: |  | ||||||
|           repository: actions/checkout # hardcoded, otherwise doesn't work from a fork |  | ||||||
|           ref: test-data/v2/lfs |  | ||||||
|           path: lfs |  | ||||||
|           lfs: true |  | ||||||
|       - name: Verify LFS |  | ||||||
|         shell: bash |  | ||||||
|         run: __test__/verify-lfs.sh |  | ||||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,2 +0,0 @@ | |||||||
| lib/ |  | ||||||
| node_modules/ |  | ||||||
| @@ -1,3 +0,0 @@ | |||||||
| dist/ |  | ||||||
| lib/ |  | ||||||
| node_modules/ |  | ||||||
| @@ -1,11 +0,0 @@ | |||||||
| { |  | ||||||
|   "printWidth": 80, |  | ||||||
|   "tabWidth": 2, |  | ||||||
|   "useTabs": false, |  | ||||||
|   "semi": false, |  | ||||||
|   "singleQuote": true, |  | ||||||
|   "trailingComma": "none", |  | ||||||
|   "bracketSpacing": false, |  | ||||||
|   "arrowParens": "avoid", |  | ||||||
|   "parser": "typescript" |  | ||||||
| } |  | ||||||
							
								
								
									
										23
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,23 +0,0 @@ | |||||||
| # Changelog |  | ||||||
|  |  | ||||||
| ## v2 (beta) |  | ||||||
|  |  | ||||||
| - Improved fetch performance |  | ||||||
|   - The default behavior now fetches only the SHA being checked-out |  | ||||||
| - Script authenticated git commands |  | ||||||
|   - Persists `with.token` in the local git config |  | ||||||
|   - Enables your scripts to run authenticated git commands |  | ||||||
|   - Post-job cleanup removes the token |  | ||||||
|   - Coming soon: Opt out by setting `with.persist-credentials` to `false` |  | ||||||
| - Creates a local branch |  | ||||||
|   - No longer detached HEAD when checking out a branch |  | ||||||
|   - A local branch is created with the corresponding upstream branch set |  | ||||||
| - Improved layout |  | ||||||
|   - `with.path` is always relative to `github.workspace` |  | ||||||
|   - Aligns better with container actions, where `github.workspace` gets mapped in |  | ||||||
| - Removed input `submodules` |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ## v1 |  | ||||||
|  |  | ||||||
| Refer [here](https://github.com/actions/checkout/blob/v1/CHANGELOG.md) for the V1 changelog |  | ||||||
							
								
								
									
										85
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,86 +1,35 @@ | |||||||
| <p align="center"> | # checkout | ||||||
|   <a href="https://github.com/actions/checkout"><img alt="GitHub Actions status" src="https://github.com/actions/checkout/workflows/test-local/badge.svg"></a> |  | ||||||
| </p> |  | ||||||
|  |  | ||||||
| # Checkout V2 beta | This action checks out your repository to `$GITHUB_WORKSPACE`, so that your workflow can access the contents of your repository. | ||||||
|  |  | ||||||
| This action checks-out your repository under `$GITHUB_WORKSPACE`, so your workflow can access it. | By default, this is equivalent to running `git fetch` and `git checkout $GITHUB_SHA`, so that you'll always have your repo contents at the version that triggered the workflow. | ||||||
|  | See [here](https://help.github.com/en/articles/events-that-trigger-workflows) to learn what `$GITHUB_SHA` is for different kinds of events. | ||||||
| By default, the repository that triggered the workflow is checked-out, for the ref/SHA that triggered the event. |  | ||||||
|  |  | ||||||
| Refer [here](https://help.github.com/en/articles/events-that-trigger-workflows) to learn which commit `$GITHUB_SHA` points to for different events. |  | ||||||
|  |  | ||||||
| Changes in V2: |  | ||||||
| - Improved fetch performance |  | ||||||
|   - The default behavior now fetches only the SHA being checked-out |  | ||||||
| - Script authenticated git commands |  | ||||||
|   - Persists `with.token` in the local git config |  | ||||||
|   - Enables your scripts to run authenticated git commands |  | ||||||
|   - Post-job cleanup removes the token |  | ||||||
|   - Coming soon: Opt out by setting `with.persist-credentials` to `false` |  | ||||||
| - Creates a local branch |  | ||||||
|   - No longer detached HEAD when checking out a branch |  | ||||||
|   - A local branch is created with the corresponding upstream branch set |  | ||||||
| - Improved layout |  | ||||||
|   - `with.path` is always relative to `github.workspace` |  | ||||||
|   - Aligns better with container actions, where `github.workspace` gets mapped in |  | ||||||
| - Removed input `submodules` |  | ||||||
|  |  | ||||||
| Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous versions. |  | ||||||
|  |  | ||||||
| # Usage | # Usage | ||||||
|  |  | ||||||
| <!-- start usage --> | See [action.yml](action.yml) | ||||||
|  |  | ||||||
|  | Basic: | ||||||
|  |  | ||||||
| ```yaml | ```yaml | ||||||
| - uses: actions/checkout@v2-beta | steps: | ||||||
|  | - uses: actions/checkout@master | ||||||
|  | - uses: actions/setup-node@master | ||||||
|   with: |   with: | ||||||
|     # Repository name with owner. For example, actions/checkout |     node-version: 10.x  | ||||||
|     # Default: ${{ github.repository }} | - run: npm install | ||||||
|     repository: '' | - run: npm test | ||||||
|  |  | ||||||
|     # Ref to checkout (SHA, branch, tag). For the repository that triggered the |  | ||||||
|     # workflow, defaults to the ref/SHA for the event. Otherwise defaults to master. |  | ||||||
|     ref: '' |  | ||||||
|  |  | ||||||
|     # Access token for clone repository |  | ||||||
|     # Default: ${{ github.token }} |  | ||||||
|     token: '' |  | ||||||
|  |  | ||||||
|     # Relative path under $GITHUB_WORKSPACE to place the repository |  | ||||||
|     path: '' |  | ||||||
|  |  | ||||||
|     # Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching |  | ||||||
|     # Default: true |  | ||||||
|     clean: '' |  | ||||||
|  |  | ||||||
|     # Number of commits to fetch. 0 indicates all history. |  | ||||||
|     # Default: 1 |  | ||||||
|     fetch-depth: '' |  | ||||||
|  |  | ||||||
|     # Whether to download Git-LFS files |  | ||||||
|     # Default: false |  | ||||||
|     lfs: '' |  | ||||||
| ``` | ``` | ||||||
| <!-- end usage --> |  | ||||||
|  |  | ||||||
| ## Checkout a different branch | By default, the branch or tag ref that triggered the workflow will be checked out. If you wish to check out a different branch, specify that using `with.ref`: | ||||||
|  |  | ||||||
| ```yaml | ```yaml | ||||||
| - uses: actions/checkout@preview | - uses: actions/checkout@master | ||||||
|   with: |   with: | ||||||
|     ref: some-branch |     ref: some-branch | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ## Checkout a different, private repository | For more details, see [Contexts and expression syntax for GitHub Actions](https://help.github.com/en/articles/contexts-and-expression-syntax-for-github-actions) | ||||||
|  |  | ||||||
| ```yaml |  | ||||||
| - uses: actions/checkout@preview |  | ||||||
|   with: |  | ||||||
|     repository: myAccount/myRepository |  | ||||||
|     ref: refs/heads/master |  | ||||||
|     token: ${{ secrets.GitHub_PAT }} # `GitHub_PAT` is a secret that contains your PAT |  | ||||||
| ``` |  | ||||||
| > - `${{ github.token }}` is scoped to the current repository, so if you want to checkout another repository that is private you will need to provide your own [PAT](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). |  | ||||||
|  |  | ||||||
| # License | # License | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,45 +0,0 @@ | |||||||
| import {GitVersion} from '../lib/git-version' |  | ||||||
|  |  | ||||||
| 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() |  | ||||||
|   }) |  | ||||||
| }) |  | ||||||
| @@ -1,120 +0,0 @@ | |||||||
| import * as assert from 'assert' |  | ||||||
| import * as path from 'path' |  | ||||||
| import {ISourceSettings} from '../lib/git-source-provider' |  | ||||||
|  |  | ||||||
| const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE'] |  | ||||||
| const gitHubWorkspace = path.resolve('/checkout-tests/workspace') |  | ||||||
|  |  | ||||||
| // Late bind |  | ||||||
| let inputHelper: any |  | ||||||
|  |  | ||||||
| // Mock @actions/core |  | ||||||
| let inputs = {} as any |  | ||||||
| const mockCore = jest.genMockFromModule('@actions/core') as any |  | ||||||
| mockCore.getInput = (name: string) => { |  | ||||||
|   return inputs[name] |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Mock @actions/github |  | ||||||
| const mockGitHub = jest.genMockFromModule('@actions/github') as any |  | ||||||
| mockGitHub.context = { |  | ||||||
|   repo: { |  | ||||||
|     owner: 'some-owner', |  | ||||||
|     repo: 'some-repo' |  | ||||||
|   }, |  | ||||||
|   ref: 'refs/heads/some-ref', |  | ||||||
|   sha: '1234567890123456789012345678901234567890' |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Mock ./fs-helper |  | ||||||
| const mockFSHelper = jest.genMockFromModule('../lib/fs-helper') as any |  | ||||||
| mockFSHelper.directoryExistsSync = (path: string) => path == gitHubWorkspace |  | ||||||
|  |  | ||||||
| describe('input-helper tests', () => { |  | ||||||
|   beforeAll(() => { |  | ||||||
|     // GitHub workspace |  | ||||||
|     process.env['GITHUB_WORKSPACE'] = gitHubWorkspace |  | ||||||
|  |  | ||||||
|     // Mocks |  | ||||||
|     jest.setMock('@actions/core', mockCore) |  | ||||||
|     jest.setMock('@actions/github', mockGitHub) |  | ||||||
|     jest.setMock('../lib/fs-helper', mockFSHelper) |  | ||||||
|  |  | ||||||
|     // Now import |  | ||||||
|     inputHelper = require('../lib/input-helper') |  | ||||||
|   }) |  | ||||||
|  |  | ||||||
|   beforeEach(() => { |  | ||||||
|     // Reset inputs |  | ||||||
|     inputs = {} |  | ||||||
|   }) |  | ||||||
|  |  | ||||||
|   afterAll(() => { |  | ||||||
|     // Reset GitHub workspace |  | ||||||
|     delete process.env['GITHUB_WORKSPACE'] |  | ||||||
|     if (originalGitHubWorkspace) { |  | ||||||
|       process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Reset modules |  | ||||||
|     jest.resetModules() |  | ||||||
|   }) |  | ||||||
|  |  | ||||||
|   it('sets defaults', () => { |  | ||||||
|     const settings: ISourceSettings = inputHelper.getInputs() |  | ||||||
|     expect(settings).toBeTruthy() |  | ||||||
|     expect(settings.accessToken).toBeFalsy() |  | ||||||
|     expect(settings.clean).toBe(true) |  | ||||||
|     expect(settings.commit).toBeTruthy() |  | ||||||
|     expect(settings.commit).toBe('1234567890123456789012345678901234567890') |  | ||||||
|     expect(settings.fetchDepth).toBe(1) |  | ||||||
|     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) |  | ||||||
|   }) |  | ||||||
|  |  | ||||||
|   it('requires qualified repo', () => { |  | ||||||
|     inputs.repository = 'some-unqualified-repo' |  | ||||||
|     assert.throws(() => { |  | ||||||
|       inputHelper.getInputs() |  | ||||||
|     }, /Invalid repository 'some-unqualified-repo'/) |  | ||||||
|   }) |  | ||||||
|  |  | ||||||
|   it('roots path', () => { |  | ||||||
|     inputs.path = 'some-directory/some-subdirectory' |  | ||||||
|     const settings: ISourceSettings = inputHelper.getInputs() |  | ||||||
|     expect(settings.repositoryPath).toBe( |  | ||||||
|       path.join(gitHubWorkspace, 'some-directory', 'some-subdirectory') |  | ||||||
|     ) |  | ||||||
|   }) |  | ||||||
|  |  | ||||||
|   it('sets correct default ref/sha for other repo', () => { |  | ||||||
|     inputs.repository = 'some-owner/some-other-repo' |  | ||||||
|     const settings: ISourceSettings = inputHelper.getInputs() |  | ||||||
|     expect(settings.ref).toBe('refs/heads/master') |  | ||||||
|     expect(settings.commit).toBeFalsy() |  | ||||||
|   }) |  | ||||||
|  |  | ||||||
|   it('sets ref to empty when explicit sha', () => { |  | ||||||
|     inputs.ref = '1111111111222222222233333333334444444444' |  | ||||||
|     const settings: ISourceSettings = inputHelper.getInputs() |  | ||||||
|     expect(settings.ref).toBeFalsy() |  | ||||||
|     expect(settings.commit).toBe('1111111111222222222233333333334444444444') |  | ||||||
|   }) |  | ||||||
|  |  | ||||||
|   it('sets sha to empty when explicit ref', () => { |  | ||||||
|     inputs.ref = 'refs/heads/some-other-ref' |  | ||||||
|     const settings: ISourceSettings = inputHelper.getInputs() |  | ||||||
|     expect(settings.ref).toBe('refs/heads/some-other-ref') |  | ||||||
|     expect(settings.commit).toBeFalsy() |  | ||||||
|   }) |  | ||||||
|  |  | ||||||
|   it('gives good error message for submodules input', () => { |  | ||||||
|     inputs.submodules = 'true' |  | ||||||
|     assert.throws(() => { |  | ||||||
|       inputHelper.getInputs() |  | ||||||
|     }, /The input 'submodules' is not supported/) |  | ||||||
|   }) |  | ||||||
| }) |  | ||||||
| @@ -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,168 +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.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.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 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.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,10 +0,0 @@ | |||||||
| #!/bin/bash |  | ||||||
|  |  | ||||||
| if [ ! -f "./basic/basic-file.txt" ]; then |  | ||||||
|     echo "Expected basic file does not exist" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| # Verify auth token |  | ||||||
| cd basic |  | ||||||
| git fetch |  | ||||||
| @@ -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,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 all" |  | ||||||
|     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,11 +0,0 @@ | |||||||
| #!/bin/bash |  | ||||||
|  |  | ||||||
| if [ ! -f "./submodules-not-checked-out/regular-file.txt" ]; then |  | ||||||
|     echo "Expected regular file does not exist" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| if [ -f "./submodules-not-checked-out/submodule-level-1/submodule-file.txt" ]; then |  | ||||||
|     echo "Unexpected submodule file exists" |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
							
								
								
									
										31
									
								
								action.yml
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								action.yml
									
									
									
									
									
								
							| @@ -1,28 +1,23 @@ | |||||||
| name: 'Checkout' | name: 'Checkout' | ||||||
| description: 'Checkout a Git repository' | description: 'Checkout a Git repository.' | ||||||
| inputs:  | inputs:  | ||||||
|   repository: |   repository: | ||||||
|     description: 'Repository name with owner. For example, actions/checkout' |     description: 'Repository name' | ||||||
|     default: ${{ github.repository }} |  | ||||||
|   ref: |   ref: | ||||||
|     description: > |     description: 'Ref to checkout (SHA, branch, tag)' | ||||||
|       Ref to checkout (SHA, branch, tag). For the repository that triggered the |  | ||||||
|       workflow, defaults to the ref/SHA for the event. Otherwise defaults to master. |  | ||||||
|   token: |   token: | ||||||
|     description: 'Access token for clone repository' |     description: 'Access token for clone repository' | ||||||
|     default: ${{ github.token }} |  | ||||||
|   path: |  | ||||||
|     description: 'Relative path under $GITHUB_WORKSPACE to place the repository' |  | ||||||
|   clean: |   clean: | ||||||
|     description: 'Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching' |     description: 'If true, execute `execute git clean -ffdx && git reset --hard HEAD` before fetching' | ||||||
|     default: true |     default: true | ||||||
|   fetch-depth: |   submodules: | ||||||
|     description: 'Number of commits to fetch. 0 indicates all history.' |     description: 'Whether to include submodules: false to exclude submodules, true to include only one level of submodules, or recursive to recursively clone submodules; defaults to false' | ||||||
|     default: 1 |  | ||||||
|   lfs: |   lfs: | ||||||
|     description: 'Whether to download Git-LFS files' |     description: 'Whether to download Git-LFS files; defaults to false' | ||||||
|     default: false |   fetch-depth: | ||||||
|  |     description: 'The depth of commits to ask Git to fetch; defaults to no limit'   | ||||||
|  |   path: | ||||||
|  |     description: 'Optional path to check out source code'   | ||||||
| runs: | runs: | ||||||
|   using: node12 |   # Plugins live on the runner and are only available to a certain set of first party actions. | ||||||
|   main: dist/index.js |   plugin: 'checkout' | ||||||
|   post: dist/index.js |  | ||||||
|   | |||||||
							
								
								
									
										13338
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13338
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										13
									
								
								dist/problem-matcher.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								dist/problem-matcher.json
									
									
									
									
										vendored
									
									
								
							| @@ -1,13 +0,0 @@ | |||||||
| { |  | ||||||
|     "problemMatcher": [ |  | ||||||
|         { |  | ||||||
|             "owner": "checkout-git", |  | ||||||
|             "pattern": [ |  | ||||||
|                 { |  | ||||||
|                     "regexp": "^(fatal|error): (.*)$", |  | ||||||
|                     "message": 2 |  | ||||||
|                 } |  | ||||||
|             ] |  | ||||||
|         } |  | ||||||
|     ] |  | ||||||
| } |  | ||||||
| @@ -1,11 +0,0 @@ | |||||||
| module.exports = { |  | ||||||
|   clearMocks: true, |  | ||||||
|   moduleFileExtensions: ['js', 'ts'], |  | ||||||
|   testEnvironment: 'node', |  | ||||||
|   testMatch: ['**/*.test.ts'], |  | ||||||
|   testRunner: 'jest-circus/runner', |  | ||||||
|   transform: { |  | ||||||
|     '^.+\\.ts$': 'ts-jest' |  | ||||||
|   }, |  | ||||||
|   verbose: true |  | ||||||
| } |  | ||||||
							
								
								
									
										7025
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										7025
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										52
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,52 +0,0 @@ | |||||||
| { |  | ||||||
|   "name": "checkout", |  | ||||||
|   "version": "2.0.0", |  | ||||||
|   "description": "checkout action", |  | ||||||
|   "main": "lib/main.js", |  | ||||||
|   "scripts": { |  | ||||||
|     "build": "tsc", |  | ||||||
|     "format": "prettier --write **/*.ts", |  | ||||||
|     "format-check": "prettier --check **/*.ts", |  | ||||||
|     "lint": "eslint src/**/*.ts", |  | ||||||
|     "pack": "ncc build", |  | ||||||
|     "gendocs": "node lib/misc/generate-docs.js", |  | ||||||
|     "test": "jest", |  | ||||||
|     "all": "npm run build && npm run format && npm run lint && npm run pack && npm run gendocs && npm test" |  | ||||||
|   }, |  | ||||||
|   "repository": { |  | ||||||
|     "type": "git", |  | ||||||
|     "url": "git+https://github.com/actions/checkout.git" |  | ||||||
|   }, |  | ||||||
|   "keywords": [ |  | ||||||
|     "github", |  | ||||||
|     "actions", |  | ||||||
|     "checkout" |  | ||||||
|   ], |  | ||||||
|   "author": "GitHub", |  | ||||||
|   "license": "MIT", |  | ||||||
|   "bugs": { |  | ||||||
|     "url": "https://github.com/actions/checkout/issues" |  | ||||||
|   }, |  | ||||||
|   "homepage": "https://github.com/actions/checkout#readme", |  | ||||||
|   "dependencies": { |  | ||||||
|     "@actions/core": "^1.1.3", |  | ||||||
|     "@actions/exec": "^1.0.1", |  | ||||||
|     "@actions/github": "^1.1.0", |  | ||||||
|     "@actions/io": "^1.0.1" |  | ||||||
|   }, |  | ||||||
|   "devDependencies": { |  | ||||||
|     "@types/jest": "^24.0.23", |  | ||||||
|     "@types/node": "^12.7.12", |  | ||||||
|     "@typescript-eslint/parser": "^2.8.0", |  | ||||||
|     "@zeit/ncc": "^0.20.5", |  | ||||||
|     "eslint": "^5.16.0", |  | ||||||
|     "eslint-plugin-github": "^2.0.0", |  | ||||||
|     "eslint-plugin-jest": "^22.21.0", |  | ||||||
|     "jest": "^24.9.0", |  | ||||||
|     "jest-circus": "^24.9.0", |  | ||||||
|     "js-yaml": "^3.13.1", |  | ||||||
|     "prettier": "^1.19.1", |  | ||||||
|     "ts-jest": "^24.2.0", |  | ||||||
|     "typescript": "^3.6.4" |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -1,77 +0,0 @@ | |||||||
| import * as fs from 'fs' |  | ||||||
|  |  | ||||||
| export function directoryExistsSync(path: string, required?: boolean): boolean { |  | ||||||
|   if (!path) { |  | ||||||
|     throw new Error("Arg 'path' must not be empty") |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   let stats: fs.Stats |  | ||||||
|   try { |  | ||||||
|     stats = fs.statSync(path) |  | ||||||
|   } catch (error) { |  | ||||||
|     if (error.code === 'ENOENT') { |  | ||||||
|       if (!required) { |  | ||||||
|         return false |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       throw new Error(`Directory '${path}' does not exist`) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     throw new Error( |  | ||||||
|       `Encountered an error when checking whether path '${path}' exists: ${error.message}` |  | ||||||
|     ) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if (stats.isDirectory()) { |  | ||||||
|     return true |  | ||||||
|   } else if (!required) { |  | ||||||
|     return false |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   throw new Error(`Directory '${path}' does not exist`) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export function existsSync(path: string): boolean { |  | ||||||
|   if (!path) { |  | ||||||
|     throw new Error("Arg 'path' must not be empty") |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   try { |  | ||||||
|     fs.statSync(path) |  | ||||||
|   } catch (error) { |  | ||||||
|     if (error.code === 'ENOENT') { |  | ||||||
|       return false |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     throw new Error( |  | ||||||
|       `Encountered an error when checking whether path '${path}' exists: ${error.message}` |  | ||||||
|     ) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return true |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export function fileExistsSync(path: string): boolean { |  | ||||||
|   if (!path) { |  | ||||||
|     throw new Error("Arg 'path' must not be empty") |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   let stats: fs.Stats |  | ||||||
|   try { |  | ||||||
|     stats = fs.statSync(path) |  | ||||||
|   } catch (error) { |  | ||||||
|     if (error.code === 'ENOENT') { |  | ||||||
|       return false |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     throw new Error( |  | ||||||
|       `Encountered an error when checking whether path '${path}' exists: ${error.message}` |  | ||||||
|     ) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if (!stats.isDirectory()) { |  | ||||||
|     return true |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return false |  | ||||||
| } |  | ||||||
| @@ -1,399 +0,0 @@ | |||||||
| import * as core from '@actions/core' |  | ||||||
| import * as exec from '@actions/exec' |  | ||||||
| import * as fshelper from './fs-helper' |  | ||||||
| import * as io from '@actions/io' |  | ||||||
| import * as path from 'path' |  | ||||||
| import {GitVersion} from './git-version' |  | ||||||
|  |  | ||||||
| export interface IGitCommandManager { |  | ||||||
|   branchDelete(remote: boolean, branch: string): Promise<void> |  | ||||||
|   branchExists(remote: boolean, pattern: string): Promise<boolean> |  | ||||||
|   branchList(remote: boolean): Promise<string[]> |  | ||||||
|   checkout(ref: string, startPoint: string): Promise<void> |  | ||||||
|   checkoutDetach(): Promise<void> |  | ||||||
|   config(configKey: string, configValue: string): Promise<void> |  | ||||||
|   configExists(configKey: string): Promise<boolean> |  | ||||||
|   fetch(fetchDepth: number, refSpec: string[]): Promise<void> |  | ||||||
|   getWorkingDirectory(): string |  | ||||||
|   init(): Promise<void> |  | ||||||
|   isDetached(): Promise<boolean> |  | ||||||
|   lfsFetch(ref: string): Promise<void> |  | ||||||
|   lfsInstall(): Promise<void> |  | ||||||
|   log1(): Promise<void> |  | ||||||
|   remoteAdd(remoteName: string, remoteUrl: string): Promise<void> |  | ||||||
|   tagExists(pattern: string): Promise<boolean> |  | ||||||
|   tryClean(): Promise<boolean> |  | ||||||
|   tryConfigUnset(configKey: string): Promise<boolean> |  | ||||||
|   tryDisableAutomaticGarbageCollection(): Promise<boolean> |  | ||||||
|   tryGetFetchUrl(): Promise<string> |  | ||||||
|   tryReset(): Promise<boolean> |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export async function CreateCommandManager( |  | ||||||
|   workingDirectory: string, |  | ||||||
|   lfs: boolean |  | ||||||
| ): Promise<IGitCommandManager> { |  | ||||||
|   return await GitCommandManager.createCommandManager(workingDirectory, lfs) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| class GitCommandManager { |  | ||||||
|   private gitEnv = { |  | ||||||
|     GIT_TERMINAL_PROMPT: '0', // Disable git prompt |  | ||||||
|     GCM_INTERACTIVE: 'Never' // Disable prompting for git credential manager |  | ||||||
|   } |  | ||||||
|   private gitPath = '' |  | ||||||
|   private lfs = false |  | ||||||
|   private workingDirectory = '' |  | ||||||
|  |  | ||||||
|   // Private constructor; use createCommandManager() |  | ||||||
|   private constructor() {} |  | ||||||
|  |  | ||||||
|   async branchDelete(remote: boolean, branch: string): Promise<void> { |  | ||||||
|     const args = ['branch', '--delete', '--force'] |  | ||||||
|     if (remote) { |  | ||||||
|       args.push('--remote') |  | ||||||
|     } |  | ||||||
|     args.push(branch) |  | ||||||
|  |  | ||||||
|     await this.execGit(args) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async branchExists(remote: boolean, pattern: string): Promise<boolean> { |  | ||||||
|     const args = ['branch', '--list'] |  | ||||||
|     if (remote) { |  | ||||||
|       args.push('--remote') |  | ||||||
|     } |  | ||||||
|     args.push(pattern) |  | ||||||
|  |  | ||||||
|     const output = await this.execGit(args) |  | ||||||
|     return !!output.stdout.trim() |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async branchList(remote: boolean): Promise<string[]> { |  | ||||||
|     const result: string[] = [] |  | ||||||
|  |  | ||||||
|     // Note, this implementation uses "rev-parse --symbolic" because the output from |  | ||||||
|     // "branch --list" is more difficult when in a detached HEAD state. |  | ||||||
|  |  | ||||||
|     const args = ['rev-parse', '--symbolic'] |  | ||||||
|     if (remote) { |  | ||||||
|       args.push('--remotes=origin') |  | ||||||
|     } else { |  | ||||||
|       args.push('--branches') |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const output = await this.execGit(args) |  | ||||||
|  |  | ||||||
|     for (let branch of output.stdout.trim().split('\n')) { |  | ||||||
|       branch = branch.trim() |  | ||||||
|       if (branch) { |  | ||||||
|         result.push(branch) |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return result |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async checkout(ref: string, startPoint: string): Promise<void> { |  | ||||||
|     const args = ['checkout', '--progress', '--force'] |  | ||||||
|     if (startPoint) { |  | ||||||
|       args.push('-B', ref, startPoint) |  | ||||||
|     } else { |  | ||||||
|       args.push(ref) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     await this.execGit(args) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async checkoutDetach(): Promise<void> { |  | ||||||
|     const args = ['checkout', '--detach'] |  | ||||||
|     await this.execGit(args) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async config(configKey: string, configValue: string): Promise<void> { |  | ||||||
|     await this.execGit(['config', configKey, configValue]) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async configExists(configKey: string): Promise<boolean> { |  | ||||||
|     const pattern = configKey.replace(/[^a-zA-Z0-9_]/g, x => { |  | ||||||
|       return `\\${x}` |  | ||||||
|     }) |  | ||||||
|     const output = await this.execGit( |  | ||||||
|       ['config', '--name-only', '--get-regexp', pattern], |  | ||||||
|       true |  | ||||||
|     ) |  | ||||||
|     return output.exitCode === 0 |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async fetch(fetchDepth: number, refSpec: string[]): Promise<void> { |  | ||||||
|     const args = [ |  | ||||||
|       '-c', |  | ||||||
|       'protocol.version=2', |  | ||||||
|       'fetch', |  | ||||||
|       '--no-tags', |  | ||||||
|       '--prune', |  | ||||||
|       '--progress', |  | ||||||
|       '--no-recurse-submodules' |  | ||||||
|     ] |  | ||||||
|     if (fetchDepth > 0) { |  | ||||||
|       args.push(`--depth=${fetchDepth}`) |  | ||||||
|     } else if ( |  | ||||||
|       fshelper.fileExistsSync( |  | ||||||
|         path.join(this.workingDirectory, '.git', 'shallow') |  | ||||||
|       ) |  | ||||||
|     ) { |  | ||||||
|       args.push('--unshallow') |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     args.push('origin') |  | ||||||
|     for (const arg of refSpec) { |  | ||||||
|       args.push(arg) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     let attempt = 1 |  | ||||||
|     const maxAttempts = 3 |  | ||||||
|     while (attempt <= maxAttempts) { |  | ||||||
|       const allowAllExitCodes = attempt < maxAttempts |  | ||||||
|       const output = await this.execGit(args, allowAllExitCodes) |  | ||||||
|       if (output.exitCode === 0) { |  | ||||||
|         break |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       const seconds = this.getRandomIntInclusive(1, 10) |  | ||||||
|       core.warning( |  | ||||||
|         `Git fetch failed with exit code ${output.exitCode}. Waiting ${seconds} seconds before trying again.` |  | ||||||
|       ) |  | ||||||
|       await this.sleep(seconds * 1000) |  | ||||||
|       attempt++ |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   getWorkingDirectory(): string { |  | ||||||
|     return this.workingDirectory |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async init(): Promise<void> { |  | ||||||
|     await this.execGit(['init', this.workingDirectory]) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async isDetached(): Promise<boolean> { |  | ||||||
|     // Note, this implementation uses "branch --show-current" because |  | ||||||
|     // "rev-parse --symbolic-full-name HEAD" can fail on a new repo |  | ||||||
|     // with nothing checked out. |  | ||||||
|  |  | ||||||
|     const output = await this.execGit(['branch', '--show-current']) |  | ||||||
|     return output.stdout.trim() === '' |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async lfsFetch(ref: string): Promise<void> { |  | ||||||
|     const args = ['lfs', 'fetch', 'origin', ref] |  | ||||||
|  |  | ||||||
|     let attempt = 1 |  | ||||||
|     const maxAttempts = 3 |  | ||||||
|     while (attempt <= maxAttempts) { |  | ||||||
|       const allowAllExitCodes = attempt < maxAttempts |  | ||||||
|       const output = await this.execGit(args, allowAllExitCodes) |  | ||||||
|       if (output.exitCode === 0) { |  | ||||||
|         break |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       const seconds = this.getRandomIntInclusive(1, 10) |  | ||||||
|       core.warning( |  | ||||||
|         `Git lfs fetch failed with exit code ${output.exitCode}. Waiting ${seconds} seconds before trying again.` |  | ||||||
|       ) |  | ||||||
|       await this.sleep(seconds * 1000) |  | ||||||
|       attempt++ |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async lfsInstall(): Promise<void> { |  | ||||||
|     await this.execGit(['lfs', 'install', '--local']) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async log1(): Promise<void> { |  | ||||||
|     await this.execGit(['log', '-1']) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async remoteAdd(remoteName: string, remoteUrl: string): Promise<void> { |  | ||||||
|     await this.execGit(['remote', 'add', remoteName, remoteUrl]) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async tagExists(pattern: string): Promise<boolean> { |  | ||||||
|     const output = await this.execGit(['tag', '--list', pattern]) |  | ||||||
|     return !!output.stdout.trim() |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async tryClean(): Promise<boolean> { |  | ||||||
|     const output = await this.execGit(['clean', '-ffdx'], true) |  | ||||||
|     return output.exitCode === 0 |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async tryConfigUnset(configKey: string): Promise<boolean> { |  | ||||||
|     const output = await this.execGit( |  | ||||||
|       ['config', '--unset-all', configKey], |  | ||||||
|       true |  | ||||||
|     ) |  | ||||||
|     return output.exitCode === 0 |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async tryDisableAutomaticGarbageCollection(): Promise<boolean> { |  | ||||||
|     const output = await this.execGit(['config', 'gc.auto', '0'], true) |  | ||||||
|     return output.exitCode === 0 |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async tryGetFetchUrl(): Promise<string> { |  | ||||||
|     const output = await this.execGit( |  | ||||||
|       ['config', '--get', 'remote.origin.url'], |  | ||||||
|       true |  | ||||||
|     ) |  | ||||||
|  |  | ||||||
|     if (output.exitCode !== 0) { |  | ||||||
|       return '' |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const stdout = output.stdout.trim() |  | ||||||
|     if (stdout.includes('\n')) { |  | ||||||
|       return '' |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return stdout |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async tryReset(): Promise<boolean> { |  | ||||||
|     const output = await this.execGit(['reset', '--hard', 'HEAD'], true) |  | ||||||
|     return output.exitCode === 0 |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static async createCommandManager( |  | ||||||
|     workingDirectory: string, |  | ||||||
|     lfs: boolean |  | ||||||
|   ): Promise<GitCommandManager> { |  | ||||||
|     const result = new GitCommandManager() |  | ||||||
|     await result.initializeCommandManager(workingDirectory, lfs) |  | ||||||
|     return result |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   private async execGit( |  | ||||||
|     args: string[], |  | ||||||
|     allowAllExitCodes = false |  | ||||||
|   ): Promise<GitOutput> { |  | ||||||
|     fshelper.directoryExistsSync(this.workingDirectory, true) |  | ||||||
|  |  | ||||||
|     const result = new GitOutput() |  | ||||||
|  |  | ||||||
|     const env = {} |  | ||||||
|     for (const key of Object.keys(process.env)) { |  | ||||||
|       env[key] = process.env[key] |  | ||||||
|     } |  | ||||||
|     for (const key of Object.keys(this.gitEnv)) { |  | ||||||
|       env[key] = this.gitEnv[key] |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const stdout: string[] = [] |  | ||||||
|  |  | ||||||
|     const options = { |  | ||||||
|       cwd: this.workingDirectory, |  | ||||||
|       env, |  | ||||||
|       ignoreReturnCode: allowAllExitCodes, |  | ||||||
|       listeners: { |  | ||||||
|         stdout: (data: Buffer) => { |  | ||||||
|           stdout.push(data.toString()) |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     result.exitCode = await exec.exec(`"${this.gitPath}"`, args, options) |  | ||||||
|     result.stdout = stdout.join('') |  | ||||||
|     return result |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   private async initializeCommandManager( |  | ||||||
|     workingDirectory: string, |  | ||||||
|     lfs: boolean |  | ||||||
|   ): Promise<void> { |  | ||||||
|     this.workingDirectory = workingDirectory |  | ||||||
|  |  | ||||||
|     // Git-lfs will try to pull down assets if any of the local/user/system setting exist. |  | ||||||
|     // If the user didn't enable `LFS` in their pipeline definition, disable LFS fetch/checkout. |  | ||||||
|     this.lfs = lfs |  | ||||||
|     if (!this.lfs) { |  | ||||||
|       this.gitEnv['GIT_LFS_SKIP_SMUDGE'] = '1' |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     this.gitPath = await io.which('git', true) |  | ||||||
|  |  | ||||||
|     // Git version |  | ||||||
|     core.debug('Getting git version') |  | ||||||
|     let gitVersion = new GitVersion() |  | ||||||
|     let gitOutput = await this.execGit(['version']) |  | ||||||
|     let stdout = gitOutput.stdout.trim() |  | ||||||
|     if (!stdout.includes('\n')) { |  | ||||||
|       const match = stdout.match(/\d+\.\d+(\.\d+)?/) |  | ||||||
|       if (match) { |  | ||||||
|         gitVersion = new GitVersion(match[0]) |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     if (!gitVersion.isValid()) { |  | ||||||
|       throw new Error('Unable to determine git version') |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Minimum git version |  | ||||||
|     // Note: |  | ||||||
|     // - Auth header not supported before 2.9 |  | ||||||
|     // - Wire protocol v2 not supported before 2.18 |  | ||||||
|     const minimumGitVersion = new GitVersion('2.18') |  | ||||||
|     if (!gitVersion.checkMinimum(minimumGitVersion)) { |  | ||||||
|       throw new Error( |  | ||||||
|         `Minimum required git version is ${minimumGitVersion}. Your git ('${this.gitPath}') is ${gitVersion}` |  | ||||||
|       ) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (this.lfs) { |  | ||||||
|       // Git-lfs version |  | ||||||
|       core.debug('Getting git-lfs version') |  | ||||||
|       let gitLfsVersion = new GitVersion() |  | ||||||
|       const gitLfsPath = await io.which('git-lfs', true) |  | ||||||
|       gitOutput = await this.execGit(['lfs', 'version']) |  | ||||||
|       stdout = gitOutput.stdout.trim() |  | ||||||
|       if (!stdout.includes('\n')) { |  | ||||||
|         const match = stdout.match(/\d+\.\d+(\.\d+)?/) |  | ||||||
|         if (match) { |  | ||||||
|           gitLfsVersion = new GitVersion(match[0]) |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       if (!gitLfsVersion.isValid()) { |  | ||||||
|         throw new Error('Unable to determine git-lfs version') |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       // Minimum git-lfs version |  | ||||||
|       // Note: |  | ||||||
|       // - Auth header not supported before 2.1 |  | ||||||
|       const minimumGitLfsVersion = new GitVersion('2.1') |  | ||||||
|       if (!gitLfsVersion.checkMinimum(minimumGitLfsVersion)) { |  | ||||||
|         throw new Error( |  | ||||||
|           `Minimum required git-lfs version is ${minimumGitLfsVersion}. Your git-lfs ('${gitLfsPath}') is ${gitLfsVersion}` |  | ||||||
|         ) |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Set the user agent |  | ||||||
|     const gitHttpUserAgent = `git/${gitVersion} (github-actions-checkout)` |  | ||||||
|     core.debug(`Set git useragent to: ${gitHttpUserAgent}`) |  | ||||||
|     this.gitEnv['GIT_HTTP_USER_AGENT'] = gitHttpUserAgent |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   private getRandomIntInclusive(minimum: number, maximum: number): number { |  | ||||||
|     minimum = Math.floor(minimum) |  | ||||||
|     maximum = Math.floor(maximum) |  | ||||||
|     return Math.floor(Math.random() * (maximum - minimum + 1)) + minimum |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   private async sleep(milliseconds): Promise<void> { |  | ||||||
|     return new Promise(resolve => setTimeout(resolve, milliseconds)) |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| class GitOutput { |  | ||||||
|   stdout = '' |  | ||||||
|   exitCode = 0 |  | ||||||
| } |  | ||||||
| @@ -1,250 +0,0 @@ | |||||||
| import * as core from '@actions/core' |  | ||||||
| import * as coreCommand from '@actions/core/lib/command' |  | ||||||
| import * as fs from 'fs' |  | ||||||
| import * as fsHelper from './fs-helper' |  | ||||||
| import * as gitCommandManager from './git-command-manager' |  | ||||||
| import * as io from '@actions/io' |  | ||||||
| import * as path from 'path' |  | ||||||
| import * as refHelper from './ref-helper' |  | ||||||
| import {IGitCommandManager} from './git-command-manager' |  | ||||||
|  |  | ||||||
| const authConfigKey = `http.https://github.com/.extraheader` |  | ||||||
|  |  | ||||||
| export interface ISourceSettings { |  | ||||||
|   repositoryPath: string |  | ||||||
|   repositoryOwner: string |  | ||||||
|   repositoryName: string |  | ||||||
|   ref: string |  | ||||||
|   commit: string |  | ||||||
|   clean: boolean |  | ||||||
|   fetchDepth: number |  | ||||||
|   lfs: boolean |  | ||||||
|   accessToken: string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export async function getSource(settings: ISourceSettings): Promise<void> { |  | ||||||
|   core.info( |  | ||||||
|     `Syncing repository: ${settings.repositoryOwner}/${settings.repositoryName}` |  | ||||||
|   ) |  | ||||||
|   const repositoryUrl = `https://github.com/${encodeURIComponent( |  | ||||||
|     settings.repositoryOwner |  | ||||||
|   )}/${encodeURIComponent(settings.repositoryName)}` |  | ||||||
|  |  | ||||||
|   // Remove conflicting file path |  | ||||||
|   if (fsHelper.fileExistsSync(settings.repositoryPath)) { |  | ||||||
|     await io.rmRF(settings.repositoryPath) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Create directory |  | ||||||
|   let isExisting = true |  | ||||||
|   if (!fsHelper.directoryExistsSync(settings.repositoryPath)) { |  | ||||||
|     isExisting = false |  | ||||||
|     await io.mkdirP(settings.repositoryPath) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Git command manager |  | ||||||
|   core.info(`Working directory is '${settings.repositoryPath}'`) |  | ||||||
|   const git = await gitCommandManager.CreateCommandManager( |  | ||||||
|     settings.repositoryPath, |  | ||||||
|     settings.lfs |  | ||||||
|   ) |  | ||||||
|  |  | ||||||
|   // Try prepare existing directory, otherwise recreate |  | ||||||
|   if ( |  | ||||||
|     isExisting && |  | ||||||
|     !(await tryPrepareExistingDirectory( |  | ||||||
|       git, |  | ||||||
|       settings.repositoryPath, |  | ||||||
|       repositoryUrl, |  | ||||||
|       settings.clean |  | ||||||
|     )) |  | ||||||
|   ) { |  | ||||||
|     // Delete the contents of the directory. Don't delete the directory itself |  | ||||||
|     // since it may be the current working directory. |  | ||||||
|     core.info(`Deleting the contents of '${settings.repositoryPath}'`) |  | ||||||
|     for (const file of await fs.promises.readdir(settings.repositoryPath)) { |  | ||||||
|       await io.rmRF(path.join(settings.repositoryPath, file)) |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Initialize the repository |  | ||||||
|   if ( |  | ||||||
|     !fsHelper.directoryExistsSync(path.join(settings.repositoryPath, '.git')) |  | ||||||
|   ) { |  | ||||||
|     await git.init() |  | ||||||
|     await git.remoteAdd('origin', repositoryUrl) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Disable automatic garbage collection |  | ||||||
|   if (!(await git.tryDisableAutomaticGarbageCollection())) { |  | ||||||
|     core.warning( |  | ||||||
|       `Unable to turn off git automatic garbage collection. The git fetch operation may trigger garbage collection and cause a delay.` |  | ||||||
|     ) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Remove possible previous extraheader |  | ||||||
|   await removeGitConfig(git, authConfigKey) |  | ||||||
|  |  | ||||||
|   // Add extraheader (auth) |  | ||||||
|   const base64Credentials = Buffer.from( |  | ||||||
|     `x-access-token:${settings.accessToken}`, |  | ||||||
|     'utf8' |  | ||||||
|   ).toString('base64') |  | ||||||
|   core.setSecret(base64Credentials) |  | ||||||
|   const authConfigValue = `AUTHORIZATION: basic ${base64Credentials}` |  | ||||||
|   await git.config(authConfigKey, authConfigValue) |  | ||||||
|  |  | ||||||
|   // LFS install |  | ||||||
|   if (settings.lfs) { |  | ||||||
|     await git.lfsInstall() |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Fetch |  | ||||||
|   const refSpec = refHelper.getRefSpec(settings.ref, settings.commit) |  | ||||||
|   await git.fetch(settings.fetchDepth, refSpec) |  | ||||||
|  |  | ||||||
|   // Checkout info |  | ||||||
|   const checkoutInfo = await refHelper.getCheckoutInfo( |  | ||||||
|     git, |  | ||||||
|     settings.ref, |  | ||||||
|     settings.commit |  | ||||||
|   ) |  | ||||||
|  |  | ||||||
|   // LFS fetch |  | ||||||
|   // Explicit lfs-fetch to avoid slow checkout (fetches one lfs object at a time). |  | ||||||
|   // Explicit lfs fetch will fetch lfs objects in parallel. |  | ||||||
|   if (settings.lfs) { |  | ||||||
|     await git.lfsFetch(checkoutInfo.startPoint || checkoutInfo.ref) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Checkout |  | ||||||
|   await git.checkout(checkoutInfo.ref, checkoutInfo.startPoint) |  | ||||||
|  |  | ||||||
|   // Dump some info about the checked out commit |  | ||||||
|   await git.log1() |  | ||||||
|  |  | ||||||
|   // Set intra-task state for cleanup |  | ||||||
|   coreCommand.issueCommand( |  | ||||||
|     'save-state', |  | ||||||
|     {name: 'repositoryPath'}, |  | ||||||
|     settings.repositoryPath |  | ||||||
|   ) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export async function cleanup(repositoryPath: string): Promise<void> { |  | ||||||
|   // Repo exists? |  | ||||||
|   if (!fsHelper.fileExistsSync(path.join(repositoryPath, '.git', 'config'))) { |  | ||||||
|     return |  | ||||||
|   } |  | ||||||
|   fsHelper.directoryExistsSync(repositoryPath, true) |  | ||||||
|  |  | ||||||
|   // Remove the config key |  | ||||||
|   const git = await gitCommandManager.CreateCommandManager( |  | ||||||
|     repositoryPath, |  | ||||||
|     false |  | ||||||
|   ) |  | ||||||
|   await removeGitConfig(git, authConfigKey) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function tryPrepareExistingDirectory( |  | ||||||
|   git: IGitCommandManager, |  | ||||||
|   repositoryPath: string, |  | ||||||
|   repositoryUrl: string, |  | ||||||
|   clean: boolean |  | ||||||
| ): Promise<boolean> { |  | ||||||
|   // Fetch URL does not match |  | ||||||
|   if ( |  | ||||||
|     !fsHelper.directoryExistsSync(path.join(repositoryPath, '.git')) || |  | ||||||
|     repositoryUrl !== (await git.tryGetFetchUrl()) |  | ||||||
|   ) { |  | ||||||
|     return false |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Delete any index.lock and shallow.lock left by a previously canceled run or crashed git process |  | ||||||
|   const lockPaths = [ |  | ||||||
|     path.join(repositoryPath, '.git', 'index.lock'), |  | ||||||
|     path.join(repositoryPath, '.git', 'shallow.lock') |  | ||||||
|   ] |  | ||||||
|   for (const lockPath of lockPaths) { |  | ||||||
|     try { |  | ||||||
|       await io.rmRF(lockPath) |  | ||||||
|     } catch (error) { |  | ||||||
|       core.debug(`Unable to delete '${lockPath}'. ${error.message}`) |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   try { |  | ||||||
|     // Checkout detached HEAD |  | ||||||
|     if (!(await git.isDetached())) { |  | ||||||
|       await git.checkoutDetach() |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Remove all refs/heads/* |  | ||||||
|     let branches = await git.branchList(false) |  | ||||||
|     for (const branch of branches) { |  | ||||||
|       await git.branchDelete(false, branch) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Remove all refs/remotes/origin/* to avoid conflicts |  | ||||||
|     branches = await git.branchList(true) |  | ||||||
|     for (const branch of branches) { |  | ||||||
|       await git.branchDelete(true, branch) |  | ||||||
|     } |  | ||||||
|   } catch (error) { |  | ||||||
|     core.warning( |  | ||||||
|       `Unable to prepare the existing repository. The repository will be recreated instead.` |  | ||||||
|     ) |  | ||||||
|     return false |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Clean |  | ||||||
|   if (clean) { |  | ||||||
|     let succeeded = true |  | ||||||
|     if (!(await git.tryClean())) { |  | ||||||
|       core.debug( |  | ||||||
|         `The clean command failed. This might be caused by: 1) path too long, 2) permission issue, or 3) file in use. For futher investigation, manually run 'git clean -ffdx' on the directory '${repositoryPath}'.` |  | ||||||
|       ) |  | ||||||
|       succeeded = false |  | ||||||
|     } else if (!(await git.tryReset())) { |  | ||||||
|       succeeded = false |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (!succeeded) { |  | ||||||
|       core.warning( |  | ||||||
|         `Unable to clean or reset the repository. The repository will be recreated instead.` |  | ||||||
|       ) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return succeeded |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return true |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function removeGitConfig( |  | ||||||
|   git: IGitCommandManager, |  | ||||||
|   configKey: string |  | ||||||
| ): Promise<void> { |  | ||||||
|   if ( |  | ||||||
|     (await git.configExists(configKey)) && |  | ||||||
|     !(await git.tryConfigUnset(configKey)) |  | ||||||
|   ) { |  | ||||||
|     // Load the config contents |  | ||||||
|     core.warning( |  | ||||||
|       `Failed to remove '${configKey}' from the git config. Attempting to remove the config value by editing the file directly.` |  | ||||||
|     ) |  | ||||||
|     const configPath = path.join(git.getWorkingDirectory(), '.git', 'config') |  | ||||||
|     fsHelper.fileExistsSync(configPath) |  | ||||||
|     let contents = fs.readFileSync(configPath).toString() || '' |  | ||||||
|  |  | ||||||
|     // Filter - only includes lines that do not contain the config key |  | ||||||
|     const upperConfigKey = configKey.toUpperCase() |  | ||||||
|     const split = contents |  | ||||||
|       .split('\n') |  | ||||||
|       .filter(x => !x.toUpperCase().includes(upperConfigKey)) |  | ||||||
|     contents = split.join('\n') |  | ||||||
|  |  | ||||||
|     // Rewrite the config file |  | ||||||
|     fs.writeFileSync(configPath, contents) |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -1,77 +0,0 @@ | |||||||
| export class GitVersion { |  | ||||||
|   private readonly major: number = NaN |  | ||||||
|   private readonly minor: number = NaN |  | ||||||
|   private readonly patch: number = NaN |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Used for comparing the version of git and git-lfs against the minimum required version |  | ||||||
|    * @param version the version string, e.g. 1.2 or 1.2.3 |  | ||||||
|    */ |  | ||||||
|   constructor(version?: string) { |  | ||||||
|     if (version) { |  | ||||||
|       const match = version.match(/^(\d+)\.(\d+)(\.(\d+))?$/) |  | ||||||
|       if (match) { |  | ||||||
|         this.major = Number(match[1]) |  | ||||||
|         this.minor = Number(match[2]) |  | ||||||
|         if (match[4]) { |  | ||||||
|           this.patch = Number(match[4]) |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Compares the instance against a minimum required version |  | ||||||
|    * @param minimum Minimum version |  | ||||||
|    */ |  | ||||||
|   checkMinimum(minimum: GitVersion): boolean { |  | ||||||
|     if (!minimum.isValid()) { |  | ||||||
|       throw new Error('Arg minimum is not a valid version') |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Major is insufficient |  | ||||||
|     if (this.major < minimum.major) { |  | ||||||
|       return false |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Major is equal |  | ||||||
|     if (this.major === minimum.major) { |  | ||||||
|       // Minor is insufficient |  | ||||||
|       if (this.minor < minimum.minor) { |  | ||||||
|         return false |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       // Minor is equal |  | ||||||
|       if (this.minor === minimum.minor) { |  | ||||||
|         // Patch is insufficient |  | ||||||
|         if (this.patch && this.patch < (minimum.patch || 0)) { |  | ||||||
|           return false |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return true |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Indicates whether the instance was constructed from a valid version string |  | ||||||
|    */ |  | ||||||
|   isValid(): boolean { |  | ||||||
|     return !isNaN(this.major) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Returns the version as a string, e.g. 1.2 or 1.2.3 |  | ||||||
|    */ |  | ||||||
|   toString(): string { |  | ||||||
|     let result = '' |  | ||||||
|     if (this.isValid()) { |  | ||||||
|       result = `${this.major}.${this.minor}` |  | ||||||
|       if (!isNaN(this.patch)) { |  | ||||||
|         result += `.${this.patch}` |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return result |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -1,104 +0,0 @@ | |||||||
| import * as core from '@actions/core' |  | ||||||
| import * as fsHelper from './fs-helper' |  | ||||||
| import * as github from '@actions/github' |  | ||||||
| import * as path from 'path' |  | ||||||
| import {ISourceSettings} from './git-source-provider' |  | ||||||
|  |  | ||||||
| export function getInputs(): ISourceSettings { |  | ||||||
|   const result = ({} as unknown) as ISourceSettings |  | ||||||
|  |  | ||||||
|   // GitHub workspace |  | ||||||
|   let githubWorkspacePath = process.env['GITHUB_WORKSPACE'] |  | ||||||
|   if (!githubWorkspacePath) { |  | ||||||
|     throw new Error('GITHUB_WORKSPACE not defined') |  | ||||||
|   } |  | ||||||
|   githubWorkspacePath = path.resolve(githubWorkspacePath) |  | ||||||
|   core.debug(`GITHUB_WORKSPACE = '${githubWorkspacePath}'`) |  | ||||||
|   fsHelper.directoryExistsSync(githubWorkspacePath, true) |  | ||||||
|  |  | ||||||
|   // Qualified repository |  | ||||||
|   const qualifiedRepository = |  | ||||||
|     core.getInput('repository') || |  | ||||||
|     `${github.context.repo.owner}/${github.context.repo.repo}` |  | ||||||
|   core.debug(`qualified repository = '${qualifiedRepository}'`) |  | ||||||
|   const splitRepository = qualifiedRepository.split('/') |  | ||||||
|   if ( |  | ||||||
|     splitRepository.length !== 2 || |  | ||||||
|     !splitRepository[0] || |  | ||||||
|     !splitRepository[1] |  | ||||||
|   ) { |  | ||||||
|     throw new Error( |  | ||||||
|       `Invalid repository '${qualifiedRepository}'. Expected format {owner}/{repo}.` |  | ||||||
|     ) |  | ||||||
|   } |  | ||||||
|   result.repositoryOwner = splitRepository[0] |  | ||||||
|   result.repositoryName = splitRepository[1] |  | ||||||
|  |  | ||||||
|   // Repository path |  | ||||||
|   result.repositoryPath = core.getInput('path') || '.' |  | ||||||
|   result.repositoryPath = path.resolve( |  | ||||||
|     githubWorkspacePath, |  | ||||||
|     result.repositoryPath |  | ||||||
|   ) |  | ||||||
|   if ( |  | ||||||
|     !(result.repositoryPath + path.sep).startsWith( |  | ||||||
|       githubWorkspacePath + path.sep |  | ||||||
|     ) |  | ||||||
|   ) { |  | ||||||
|     throw new Error( |  | ||||||
|       `Repository path '${result.repositoryPath}' is not under '${githubWorkspacePath}'` |  | ||||||
|     ) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Workflow repository? |  | ||||||
|   const isWorkflowRepository = |  | ||||||
|     qualifiedRepository.toUpperCase() === |  | ||||||
|     `${github.context.repo.owner}/${github.context.repo.repo}`.toUpperCase() |  | ||||||
|  |  | ||||||
|   // Source branch, source version |  | ||||||
|   result.ref = core.getInput('ref') |  | ||||||
|   if (!result.ref) { |  | ||||||
|     if (isWorkflowRepository) { |  | ||||||
|       result.ref = github.context.ref |  | ||||||
|       result.commit = github.context.sha |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (!result.ref && !result.commit) { |  | ||||||
|       result.ref = 'refs/heads/master' |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   // SHA? |  | ||||||
|   else if (result.ref.match(/^[0-9a-fA-F]{40}$/)) { |  | ||||||
|     result.commit = result.ref |  | ||||||
|     result.ref = '' |  | ||||||
|   } |  | ||||||
|   core.debug(`ref = '${result.ref}'`) |  | ||||||
|   core.debug(`commit = '${result.commit}'`) |  | ||||||
|  |  | ||||||
|   // Clean |  | ||||||
|   result.clean = (core.getInput('clean') || 'true').toUpperCase() === 'TRUE' |  | ||||||
|   core.debug(`clean = ${result.clean}`) |  | ||||||
|  |  | ||||||
|   // Submodules |  | ||||||
|   if (core.getInput('submodules')) { |  | ||||||
|     throw new Error( |  | ||||||
|       "The input 'submodules' is not supported in actions/checkout@v2" |  | ||||||
|     ) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Fetch depth |  | ||||||
|   result.fetchDepth = Math.floor(Number(core.getInput('fetch-depth') || '1')) |  | ||||||
|   if (isNaN(result.fetchDepth) || result.fetchDepth < 0) { |  | ||||||
|     result.fetchDepth = 0 |  | ||||||
|   } |  | ||||||
|   core.debug(`fetch depth = ${result.fetchDepth}`) |  | ||||||
|  |  | ||||||
|   // LFS |  | ||||||
|   result.lfs = (core.getInput('lfs') || 'false').toUpperCase() === 'TRUE' |  | ||||||
|   core.debug(`lfs = ${result.lfs}`) |  | ||||||
|  |  | ||||||
|   // Access token |  | ||||||
|   result.accessToken = core.getInput('token') |  | ||||||
|  |  | ||||||
|   return result |  | ||||||
| } |  | ||||||
							
								
								
									
										47
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								src/main.ts
									
									
									
									
									
								
							| @@ -1,47 +0,0 @@ | |||||||
| import * as core from '@actions/core' |  | ||||||
| import * as coreCommand from '@actions/core/lib/command' |  | ||||||
| import * as gitSourceProvider from './git-source-provider' |  | ||||||
| import * as inputHelper from './input-helper' |  | ||||||
| import * as path from 'path' |  | ||||||
|  |  | ||||||
| const cleanupRepositoryPath = process.env['STATE_repositoryPath'] as string |  | ||||||
|  |  | ||||||
| async function run(): Promise<void> { |  | ||||||
|   try { |  | ||||||
|     const sourceSettings = inputHelper.getInputs() |  | ||||||
|  |  | ||||||
|     try { |  | ||||||
|       // Register problem matcher |  | ||||||
|       coreCommand.issueCommand( |  | ||||||
|         'add-matcher', |  | ||||||
|         {}, |  | ||||||
|         path.join(__dirname, 'problem-matcher.json') |  | ||||||
|       ) |  | ||||||
|  |  | ||||||
|       // Get sources |  | ||||||
|       await gitSourceProvider.getSource(sourceSettings) |  | ||||||
|     } finally { |  | ||||||
|       // Unregister problem matcher |  | ||||||
|       coreCommand.issueCommand('remove-matcher', {owner: 'checkout-git'}, '') |  | ||||||
|     } |  | ||||||
|   } catch (error) { |  | ||||||
|     core.setFailed(error.message) |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function cleanup(): Promise<void> { |  | ||||||
|   try { |  | ||||||
|     await gitSourceProvider.cleanup(cleanupRepositoryPath) |  | ||||||
|   } catch (error) { |  | ||||||
|     core.warning(error.message) |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Main |  | ||||||
| if (!cleanupRepositoryPath) { |  | ||||||
|   run() |  | ||||||
| } |  | ||||||
| // Post |  | ||||||
| else { |  | ||||||
|   cleanup() |  | ||||||
| } |  | ||||||
| @@ -1,102 +0,0 @@ | |||||||
| import * as fs from 'fs' |  | ||||||
| import * as os from 'os' |  | ||||||
| import * as path from 'path' |  | ||||||
| import * as yaml from 'js-yaml' |  | ||||||
|  |  | ||||||
| // |  | ||||||
| // SUMMARY |  | ||||||
| // |  | ||||||
| // This script rebuilds the usage section in the README.md to be consistent with the action.yml |  | ||||||
|  |  | ||||||
| function updateUsage( |  | ||||||
|   actionReference: string, |  | ||||||
|   actionYamlPath: string = 'action.yml', |  | ||||||
|   readmePath: string = 'README.md', |  | ||||||
|   startToken: string = '<!-- start usage -->', |  | ||||||
|   endToken: string = '<!-- end usage -->' |  | ||||||
| ): void { |  | ||||||
|   if (!actionReference) { |  | ||||||
|     throw new Error('Parameter actionReference must not be empty') |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Load the action.yml |  | ||||||
|   const actionYaml = yaml.safeLoad(fs.readFileSync(actionYamlPath).toString()) |  | ||||||
|  |  | ||||||
|   // Load the README |  | ||||||
|   const originalReadme = fs.readFileSync(readmePath).toString() |  | ||||||
|  |  | ||||||
|   // Find the start token |  | ||||||
|   const startTokenIndex = originalReadme.indexOf(startToken) |  | ||||||
|   if (startTokenIndex < 0) { |  | ||||||
|     throw new Error(`Start token '${startToken}' not found`) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Find the end token |  | ||||||
|   const endTokenIndex = originalReadme.indexOf(endToken) |  | ||||||
|   if (endTokenIndex < 0) { |  | ||||||
|     throw new Error(`End token '${endToken}' not found`) |  | ||||||
|   } else if (endTokenIndex < startTokenIndex) { |  | ||||||
|     throw new Error('Start token must appear before end token') |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Build the new README |  | ||||||
|   const newReadme: string[] = [] |  | ||||||
|  |  | ||||||
|   // Append the beginning |  | ||||||
|   newReadme.push(originalReadme.substr(0, startTokenIndex + startToken.length)) |  | ||||||
|  |  | ||||||
|   // Build the new usage section |  | ||||||
|   newReadme.push('```yaml', `- uses: ${actionReference}`, '  with:') |  | ||||||
|   const inputs = actionYaml.inputs |  | ||||||
|   let firstInput = true |  | ||||||
|   for (const key of Object.keys(inputs)) { |  | ||||||
|     const input = inputs[key] |  | ||||||
|  |  | ||||||
|     // Line break between inputs |  | ||||||
|     if (!firstInput) { |  | ||||||
|       newReadme.push('') |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Constrain the width of the description |  | ||||||
|     const width = 80 |  | ||||||
|     let description = input.description as string |  | ||||||
|     while (description) { |  | ||||||
|       // Longer than width? Find a space to break apart |  | ||||||
|       let segment: string = description |  | ||||||
|       if (description.length > width) { |  | ||||||
|         segment = description.substr(0, width + 1) |  | ||||||
|         while (!segment.endsWith(' ')) { |  | ||||||
|           segment = segment.substr(0, segment.length - 1) |  | ||||||
|         } |  | ||||||
|       } else { |  | ||||||
|         segment = description |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       description = description.substr(segment.length) // Remaining |  | ||||||
|       segment = segment.trimRight() // Trim the trailing space |  | ||||||
|       newReadme.push(`    # ${segment}`) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Input and default |  | ||||||
|     if (input.default !== undefined) { |  | ||||||
|       newReadme.push(`    # Default: ${input.default}`) |  | ||||||
|     } |  | ||||||
|     newReadme.push(`    ${key}: ''`) |  | ||||||
|  |  | ||||||
|     firstInput = false |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   newReadme.push('```') |  | ||||||
|  |  | ||||||
|   // Append the end |  | ||||||
|   newReadme.push(originalReadme.substr(endTokenIndex)) |  | ||||||
|  |  | ||||||
|   // Write the new README |  | ||||||
|   fs.writeFileSync(readmePath, newReadme.join(os.EOL)) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| updateUsage( |  | ||||||
|   'actions/checkout@v2-beta', |  | ||||||
|   path.join(__dirname, '..', '..', 'action.yml'), |  | ||||||
|   path.join(__dirname, '..', '..', 'README.md') |  | ||||||
| ) |  | ||||||
| @@ -1,109 +0,0 @@ | |||||||
| import {IGitCommandManager} from './git-command-manager' |  | ||||||
|  |  | ||||||
| export interface ICheckoutInfo { |  | ||||||
|   ref: string |  | ||||||
|   startPoint: string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export async function getCheckoutInfo( |  | ||||||
|   git: IGitCommandManager, |  | ||||||
|   ref: string, |  | ||||||
|   commit: string |  | ||||||
| ): Promise<ICheckoutInfo> { |  | ||||||
|   if (!git) { |  | ||||||
|     throw new Error('Arg git cannot be empty') |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if (!ref && !commit) { |  | ||||||
|     throw new Error('Args ref and commit cannot both be empty') |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   const result = ({} as unknown) as ICheckoutInfo |  | ||||||
|   const upperRef = (ref || '').toUpperCase() |  | ||||||
|  |  | ||||||
|   // SHA only |  | ||||||
|   if (!ref) { |  | ||||||
|     result.ref = commit |  | ||||||
|   } |  | ||||||
|   // refs/heads/ |  | ||||||
|   else if (upperRef.startsWith('REFS/HEADS/')) { |  | ||||||
|     const branch = ref.substring('refs/heads/'.length) |  | ||||||
|     result.ref = branch |  | ||||||
|     result.startPoint = `refs/remotes/origin/${branch}` |  | ||||||
|   } |  | ||||||
|   // refs/pull/ |  | ||||||
|   else if (upperRef.startsWith('REFS/PULL/')) { |  | ||||||
|     const branch = ref.substring('refs/pull/'.length) |  | ||||||
|     result.ref = `refs/remotes/pull/${branch}` |  | ||||||
|   } |  | ||||||
|   // refs/tags/ |  | ||||||
|   else if (upperRef.startsWith('REFS/')) { |  | ||||||
|     result.ref = ref |  | ||||||
|   } |  | ||||||
|   // Unqualified ref, check for a matching branch or tag |  | ||||||
|   else { |  | ||||||
|     if (await git.branchExists(true, `origin/${ref}`)) { |  | ||||||
|       result.ref = ref |  | ||||||
|       result.startPoint = `refs/remotes/origin/${ref}` |  | ||||||
|     } else if (await git.tagExists(`${ref}`)) { |  | ||||||
|       result.ref = `refs/tags/${ref}` |  | ||||||
|     } else { |  | ||||||
|       throw new Error( |  | ||||||
|         `A branch or tag with the name '${ref}' could not be found` |  | ||||||
|       ) |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return result |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export function getRefSpec(ref: string, commit: string): string[] { |  | ||||||
|   if (!ref && !commit) { |  | ||||||
|     throw new Error('Args ref and commit cannot both be empty') |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   const upperRef = (ref || '').toUpperCase() |  | ||||||
|  |  | ||||||
|   // SHA |  | ||||||
|   if (commit) { |  | ||||||
|     // refs/heads |  | ||||||
|     if (upperRef.startsWith('REFS/HEADS/')) { |  | ||||||
|       const branch = ref.substring('refs/heads/'.length) |  | ||||||
|       return [`+${commit}:refs/remotes/origin/${branch}`] |  | ||||||
|     } |  | ||||||
|     // refs/pull/ |  | ||||||
|     else if (upperRef.startsWith('REFS/PULL/')) { |  | ||||||
|       const branch = ref.substring('refs/pull/'.length) |  | ||||||
|       return [`+${commit}:refs/remotes/pull/${branch}`] |  | ||||||
|     } |  | ||||||
|     // refs/tags/ |  | ||||||
|     else if (upperRef.startsWith('REFS/TAGS/')) { |  | ||||||
|       return [`+${commit}:${ref}`] |  | ||||||
|     } |  | ||||||
|     // Otherwise no destination ref |  | ||||||
|     else { |  | ||||||
|       return [commit] |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   // Unqualified ref, check for a matching branch or tag |  | ||||||
|   else if (!upperRef.startsWith('REFS/')) { |  | ||||||
|     return [ |  | ||||||
|       `+refs/heads/${ref}*:refs/remotes/origin/${ref}*`, |  | ||||||
|       `+refs/tags/${ref}*:refs/tags/${ref}*` |  | ||||||
|     ] |  | ||||||
|   } |  | ||||||
|   // refs/heads/ |  | ||||||
|   else if (upperRef.startsWith('REFS/HEADS/')) { |  | ||||||
|     const branch = ref.substring('refs/heads/'.length) |  | ||||||
|     return [`+${ref}:refs/remotes/origin/${branch}`] |  | ||||||
|   } |  | ||||||
|   // refs/pull/ |  | ||||||
|   else if (upperRef.startsWith('REFS/PULL/')) { |  | ||||||
|     const branch = ref.substring('refs/pull/'.length) |  | ||||||
|     return [`+${ref}:refs/remotes/pull/${branch}`] |  | ||||||
|   } |  | ||||||
|   // refs/tags/ |  | ||||||
|   else { |  | ||||||
|     return [`+${ref}:${ref}`] |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -1,16 +0,0 @@ | |||||||
| { |  | ||||||
|   "compilerOptions": { |  | ||||||
|     "target": "es6", |  | ||||||
|     "module": "commonjs", |  | ||||||
|     "lib": [ |  | ||||||
|       "es6" |  | ||||||
|     ], |  | ||||||
|     "outDir": "./lib", |  | ||||||
|     "rootDir": "./src", |  | ||||||
|     "declaration": true, |  | ||||||
|     "strict": true, |  | ||||||
|     "noImplicitAny": false, |  | ||||||
|     "esModuleInterop": true |  | ||||||
|   }, |  | ||||||
|   "exclude": ["__test__", "lib", "node_modules"] |  | ||||||
| } |  | ||||||
		Reference in New Issue
	
	Block a user