mirror of
				https://github.com/actions/checkout.git
				synced 2025-11-04 07:48:09 +08:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			users/vanz
			...
			fhammerl/r
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					ed85399349 | 
							
								
								
									
										27
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							@@ -72,33 +72,6 @@ jobs:
 | 
			
		||||
        shell: bash
 | 
			
		||||
        run: __test__/verify-side-by-side.sh
 | 
			
		||||
 | 
			
		||||
      # Sparse checkout
 | 
			
		||||
      - name: Sparse checkout
 | 
			
		||||
        uses: ./
 | 
			
		||||
        with:
 | 
			
		||||
          sparse-checkout: |
 | 
			
		||||
            __test__
 | 
			
		||||
            .github
 | 
			
		||||
            dist
 | 
			
		||||
          path: sparse-checkout
 | 
			
		||||
 | 
			
		||||
      - name: Verify sparse checkout
 | 
			
		||||
        run: __test__/verify-sparse-checkout.sh
 | 
			
		||||
 | 
			
		||||
      # Sparse checkout (non-cone mode)
 | 
			
		||||
      - name: Sparse checkout (non-cone mode)
 | 
			
		||||
        uses: ./
 | 
			
		||||
        with:
 | 
			
		||||
          sparse-checkout: |
 | 
			
		||||
            /__test__/
 | 
			
		||||
            /.github/
 | 
			
		||||
            /dist/
 | 
			
		||||
          sparse-checkout-cone-mode: false
 | 
			
		||||
          path: sparse-checkout-non-cone-mode
 | 
			
		||||
 | 
			
		||||
      - name: Verify sparse checkout (non-cone mode)
 | 
			
		||||
        run: __test__/verify-sparse-checkout-non-cone-mode.sh
 | 
			
		||||
 | 
			
		||||
      # LFS
 | 
			
		||||
      - name: Checkout LFS
 | 
			
		||||
        uses: ./
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -1,19 +1,5 @@
 | 
			
		||||
# Changelog
 | 
			
		||||
 | 
			
		||||
## v3.5.3
 | 
			
		||||
- [Fix: Checkout fail in self-hosted runners when faulty submodule are checked-in](https://github.com/actions/checkout/pull/1196)
 | 
			
		||||
- [Fix typos found by codespell](https://github.com/actions/checkout/pull/1287)
 | 
			
		||||
- [Add support for sparse checkouts](https://github.com/actions/checkout/pull/1369)
 | 
			
		||||
 | 
			
		||||
## v3.5.2
 | 
			
		||||
- [Fix api endpoint for GHES](https://github.com/actions/checkout/pull/1289)
 | 
			
		||||
 | 
			
		||||
## v3.5.1
 | 
			
		||||
- [Fix slow checkout on Windows](https://github.com/actions/checkout/pull/1246)
 | 
			
		||||
 | 
			
		||||
## v3.5.0
 | 
			
		||||
* [Add new public key for known_hosts](https://github.com/actions/checkout/pull/1237)
 | 
			
		||||
 | 
			
		||||
## v3.4.0
 | 
			
		||||
- [Upgrade codeql actions to v2](https://github.com/actions/checkout/pull/1209)
 | 
			
		||||
- [Upgrade dependencies](https://github.com/actions/checkout/pull/1210)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								README.md
									
									
									
									
									
								
							@@ -74,15 +74,6 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
 | 
			
		||||
    # Default: true
 | 
			
		||||
    clean: ''
 | 
			
		||||
 | 
			
		||||
    # Do a sparse checkout on given patterns. Each pattern should be separated with
 | 
			
		||||
    # new lines
 | 
			
		||||
    # Default: null
 | 
			
		||||
    sparse-checkout: ''
 | 
			
		||||
 | 
			
		||||
    # Specifies whether to use cone-mode when doing a sparse checkout.
 | 
			
		||||
    # Default: true
 | 
			
		||||
    sparse-checkout-cone-mode: ''
 | 
			
		||||
 | 
			
		||||
    # Number of commits to fetch. 0 indicates all history for all branches and tags.
 | 
			
		||||
    # Default: 1
 | 
			
		||||
    fetch-depth: ''
 | 
			
		||||
@@ -115,9 +106,6 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
 | 
			
		||||
 | 
			
		||||
# Scenarios
 | 
			
		||||
 | 
			
		||||
- [Fetch only the root files](#Fetch-only-the-root-files)
 | 
			
		||||
- [Fetch only the root files and `.github` and `src` folder](#Fetch-only-the-root-files-and-github-and-src-folder)
 | 
			
		||||
- [Fetch only a single file](#Fetch-only-a-single-file)
 | 
			
		||||
- [Fetch all history for all tags and branches](#Fetch-all-history-for-all-tags-and-branches)
 | 
			
		||||
- [Checkout a different branch](#Checkout-a-different-branch)
 | 
			
		||||
- [Checkout HEAD^](#Checkout-HEAD)
 | 
			
		||||
@@ -128,34 +116,6 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
 | 
			
		||||
- [Checkout pull request on closed event](#Checkout-pull-request-on-closed-event)
 | 
			
		||||
- [Push a commit using the built-in token](#Push-a-commit-using-the-built-in-token)
 | 
			
		||||
 | 
			
		||||
## Fetch only the root files
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
- uses: actions/checkout@v3
 | 
			
		||||
  with:
 | 
			
		||||
    sparse-checkout: .
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Fetch only the root files and `.github` and `src` folder
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
- uses: actions/checkout@v3
 | 
			
		||||
  with:
 | 
			
		||||
    sparse-checkout: |
 | 
			
		||||
      .github
 | 
			
		||||
      src
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Fetch only a single file
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
- uses: actions/checkout@v3
 | 
			
		||||
  with:
 | 
			
		||||
    sparse-checkout: |
 | 
			
		||||
      README.md
 | 
			
		||||
    sparse-checkout-cone-mode: false
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Fetch all history for all tags and branches
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
 
 | 
			
		||||
@@ -94,11 +94,11 @@ describe('git-auth-helper tests', () => {
 | 
			
		||||
      `x-access-token:${settings.authToken}`,
 | 
			
		||||
      'utf8'
 | 
			
		||||
    ).toString('base64')
 | 
			
		||||
    // expect(
 | 
			
		||||
    //   configContent.indexOf(
 | 
			
		||||
    //     `http.${expectedServerUrl}/.extraheader AUTHORIZATION: basic ${basicCredential}`
 | 
			
		||||
    //   )
 | 
			
		||||
    // ).toBeGreaterThanOrEqual(0)
 | 
			
		||||
    expect(
 | 
			
		||||
      configContent.indexOf(
 | 
			
		||||
        `http.${expectedServerUrl}/.extraheader AUTHORIZATION: basic ${basicCredential}`
 | 
			
		||||
      )
 | 
			
		||||
    ).toBeGreaterThanOrEqual(0)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const configureAuth_configuresAuthHeader =
 | 
			
		||||
@@ -145,11 +145,11 @@ describe('git-auth-helper tests', () => {
 | 
			
		||||
      const configContent = (
 | 
			
		||||
        await fs.promises.readFile(localGitConfigPath)
 | 
			
		||||
      ).toString()
 | 
			
		||||
      // expect(
 | 
			
		||||
      //   configContent.indexOf(
 | 
			
		||||
      //     `http.https://github.com/.extraheader AUTHORIZATION`
 | 
			
		||||
      //   )
 | 
			
		||||
      // ).toBeGreaterThanOrEqual(0)
 | 
			
		||||
      expect(
 | 
			
		||||
        configContent.indexOf(
 | 
			
		||||
          `http.https://github.com/.extraheader AUTHORIZATION`
 | 
			
		||||
        )
 | 
			
		||||
      ).toBeGreaterThanOrEqual(0)
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
@@ -419,11 +419,11 @@ describe('git-auth-helper tests', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
      configContent.indexOf('value-from-global-config')
 | 
			
		||||
    ).toBeGreaterThanOrEqual(0)
 | 
			
		||||
    // expect(
 | 
			
		||||
    //   configContent.indexOf(
 | 
			
		||||
    //     `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}`
 | 
			
		||||
    //   )
 | 
			
		||||
    // ).toBeGreaterThanOrEqual(0)
 | 
			
		||||
    expect(
 | 
			
		||||
      configContent.indexOf(
 | 
			
		||||
        `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}`
 | 
			
		||||
      )
 | 
			
		||||
    ).toBeGreaterThanOrEqual(0)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist =
 | 
			
		||||
@@ -463,11 +463,11 @@ describe('git-auth-helper tests', () => {
 | 
			
		||||
      const configContent = (
 | 
			
		||||
        await fs.promises.readFile(path.join(git.env['HOME'], '.gitconfig'))
 | 
			
		||||
      ).toString()
 | 
			
		||||
      // expect(
 | 
			
		||||
      //   configContent.indexOf(
 | 
			
		||||
      //     `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}`
 | 
			
		||||
      //   )
 | 
			
		||||
      // ).toBeGreaterThanOrEqual(0)
 | 
			
		||||
      expect(
 | 
			
		||||
        configContent.indexOf(
 | 
			
		||||
          `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}`
 | 
			
		||||
        )
 | 
			
		||||
      ).toBeGreaterThanOrEqual(0)
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
@@ -554,7 +554,7 @@ describe('git-auth-helper tests', () => {
 | 
			
		||||
      expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch(
 | 
			
		||||
        /unset-all.*insteadOf/
 | 
			
		||||
      )
 | 
			
		||||
      // expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/)
 | 
			
		||||
      expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/)
 | 
			
		||||
      expect(mockSubmoduleForeach.mock.calls[2][0]).toMatch(
 | 
			
		||||
        /url.*insteadOf.*git@github.com:/
 | 
			
		||||
      )
 | 
			
		||||
@@ -593,7 +593,7 @@ describe('git-auth-helper tests', () => {
 | 
			
		||||
      expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch(
 | 
			
		||||
        /unset-all.*insteadOf/
 | 
			
		||||
      )
 | 
			
		||||
      // expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/)
 | 
			
		||||
      expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/)
 | 
			
		||||
      expect(mockSubmoduleForeach.mock.calls[2][0]).toMatch(/core\.sshCommand/)
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
@@ -727,8 +727,6 @@ async function setup(testName: string): Promise<void> {
 | 
			
		||||
    branchDelete: jest.fn(),
 | 
			
		||||
    branchExists: jest.fn(),
 | 
			
		||||
    branchList: jest.fn(),
 | 
			
		||||
    sparseCheckout: jest.fn(),
 | 
			
		||||
    sparseCheckoutNonConeMode: jest.fn(),
 | 
			
		||||
    checkout: jest.fn(),
 | 
			
		||||
    checkoutDetach: jest.fn(),
 | 
			
		||||
    config: jest.fn(
 | 
			
		||||
@@ -772,9 +770,6 @@ async function setup(testName: string): Promise<void> {
 | 
			
		||||
      return ''
 | 
			
		||||
    }),
 | 
			
		||||
    submoduleSync: jest.fn(),
 | 
			
		||||
    submoduleStatus: jest.fn(async () => {
 | 
			
		||||
      return true
 | 
			
		||||
    }),
 | 
			
		||||
    submoduleUpdate: jest.fn(),
 | 
			
		||||
    tagExists: jest.fn(),
 | 
			
		||||
    tryClean: jest.fn(),
 | 
			
		||||
@@ -802,8 +797,6 @@ async function setup(testName: string): Promise<void> {
 | 
			
		||||
    authToken: 'some auth token',
 | 
			
		||||
    clean: true,
 | 
			
		||||
    commit: '',
 | 
			
		||||
    sparseCheckout: [],
 | 
			
		||||
    sparseCheckoutConeMode: true,
 | 
			
		||||
    fetchDepth: 1,
 | 
			
		||||
    lfs: false,
 | 
			
		||||
    submodules: false,
 | 
			
		||||
 
 | 
			
		||||
@@ -39,12 +39,7 @@ describe('git-auth-helper tests', () => {
 | 
			
		||||
    jest.spyOn(exec, 'exec').mockImplementation(mockExec)
 | 
			
		||||
    const workingDirectory = 'test'
 | 
			
		||||
    const lfs = false
 | 
			
		||||
    const doSparseCheckout = false
 | 
			
		||||
    git = await commandManager.createCommandManager(
 | 
			
		||||
      workingDirectory,
 | 
			
		||||
      lfs,
 | 
			
		||||
      doSparseCheckout
 | 
			
		||||
    )
 | 
			
		||||
    git = await commandManager.createCommandManager(workingDirectory, lfs)
 | 
			
		||||
 | 
			
		||||
    let branches = await git.branchList(false)
 | 
			
		||||
 | 
			
		||||
@@ -75,12 +70,7 @@ describe('git-auth-helper tests', () => {
 | 
			
		||||
    jest.spyOn(exec, 'exec').mockImplementation(mockExec)
 | 
			
		||||
    const workingDirectory = 'test'
 | 
			
		||||
    const lfs = false
 | 
			
		||||
    const doSparseCheckout = false
 | 
			
		||||
    git = await commandManager.createCommandManager(
 | 
			
		||||
      workingDirectory,
 | 
			
		||||
      lfs,
 | 
			
		||||
      doSparseCheckout
 | 
			
		||||
    )
 | 
			
		||||
    git = await commandManager.createCommandManager(workingDirectory, lfs)
 | 
			
		||||
 | 
			
		||||
    let branches = await git.branchList(false)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -281,65 +281,6 @@ describe('git-directory-helper tests', () => {
 | 
			
		||||
    expect(git.branchDelete).toHaveBeenCalledWith(false, 'local-branch-2')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const cleanWhenSubmoduleStatusIsFalse =
 | 
			
		||||
    'cleans when submodule status is false'
 | 
			
		||||
 | 
			
		||||
  it(cleanWhenSubmoduleStatusIsFalse, async () => {
 | 
			
		||||
    // Arrange
 | 
			
		||||
    await setup(cleanWhenSubmoduleStatusIsFalse)
 | 
			
		||||
    await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '')
 | 
			
		||||
 | 
			
		||||
    //mock bad submodule
 | 
			
		||||
 | 
			
		||||
    const submoduleStatus = git.submoduleStatus as jest.Mock<any, any>
 | 
			
		||||
    submoduleStatus.mockImplementation(async (remote: boolean) => {
 | 
			
		||||
      return false
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    // Act
 | 
			
		||||
    await gitDirectoryHelper.prepareExistingDirectory(
 | 
			
		||||
      git,
 | 
			
		||||
      repositoryPath,
 | 
			
		||||
      repositoryUrl,
 | 
			
		||||
      clean,
 | 
			
		||||
      ref
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    // Assert
 | 
			
		||||
    const files = await fs.promises.readdir(repositoryPath)
 | 
			
		||||
    expect(files).toHaveLength(0)
 | 
			
		||||
    expect(git.tryClean).toHaveBeenCalled()
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const doesNotCleanWhenSubmoduleStatusIsTrue =
 | 
			
		||||
    'does not clean when submodule status is true'
 | 
			
		||||
 | 
			
		||||
  it(doesNotCleanWhenSubmoduleStatusIsTrue, async () => {
 | 
			
		||||
    // Arrange
 | 
			
		||||
    await setup(doesNotCleanWhenSubmoduleStatusIsTrue)
 | 
			
		||||
    await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '')
 | 
			
		||||
 | 
			
		||||
    const submoduleStatus = git.submoduleStatus as jest.Mock<any, any>
 | 
			
		||||
    submoduleStatus.mockImplementation(async (remote: boolean) => {
 | 
			
		||||
      return true
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    // Act
 | 
			
		||||
    await gitDirectoryHelper.prepareExistingDirectory(
 | 
			
		||||
      git,
 | 
			
		||||
      repositoryPath,
 | 
			
		||||
      repositoryUrl,
 | 
			
		||||
      clean,
 | 
			
		||||
      ref
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    // Assert
 | 
			
		||||
 | 
			
		||||
    const files = await fs.promises.readdir(repositoryPath)
 | 
			
		||||
    expect(files.sort()).toEqual(['.git', 'my-file'])
 | 
			
		||||
    expect(git.tryClean).toHaveBeenCalled()
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const removesLockFiles = 'removes lock files'
 | 
			
		||||
  it(removesLockFiles, async () => {
 | 
			
		||||
    // Arrange
 | 
			
		||||
@@ -462,8 +403,6 @@ async function setup(testName: string): Promise<void> {
 | 
			
		||||
    branchList: jest.fn(async () => {
 | 
			
		||||
      return []
 | 
			
		||||
    }),
 | 
			
		||||
    sparseCheckout: jest.fn(),
 | 
			
		||||
    sparseCheckoutNonConeMode: jest.fn(),
 | 
			
		||||
    checkout: jest.fn(),
 | 
			
		||||
    checkoutDetach: jest.fn(),
 | 
			
		||||
    config: jest.fn(),
 | 
			
		||||
@@ -484,9 +423,6 @@ async function setup(testName: string): Promise<void> {
 | 
			
		||||
    submoduleForeach: jest.fn(),
 | 
			
		||||
    submoduleSync: jest.fn(),
 | 
			
		||||
    submoduleUpdate: jest.fn(),
 | 
			
		||||
    submoduleStatus: jest.fn(async () => {
 | 
			
		||||
      return true
 | 
			
		||||
    }),
 | 
			
		||||
    tagExists: jest.fn(),
 | 
			
		||||
    tryClean: jest.fn(async () => {
 | 
			
		||||
      return true
 | 
			
		||||
 
 | 
			
		||||
@@ -79,8 +79,6 @@ describe('input-helper tests', () => {
 | 
			
		||||
    expect(settings.clean).toBe(true)
 | 
			
		||||
    expect(settings.commit).toBeTruthy()
 | 
			
		||||
    expect(settings.commit).toBe('1234567890123456789012345678901234567890')
 | 
			
		||||
    expect(settings.sparseCheckout).toBe(undefined)
 | 
			
		||||
    expect(settings.sparseCheckoutConeMode).toBe(true)
 | 
			
		||||
    expect(settings.fetchDepth).toBe(1)
 | 
			
		||||
    expect(settings.lfs).toBe(false)
 | 
			
		||||
    expect(settings.ref).toBe('refs/heads/some-ref')
 | 
			
		||||
 
 | 
			
		||||
@@ -1,51 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
# Verify .git folder
 | 
			
		||||
if [ ! -d "./sparse-checkout-non-cone-mode/.git" ]; then
 | 
			
		||||
  echo "Expected ./sparse-checkout-non-cone-mode/.git folder to exist"
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Verify sparse-checkout (non-cone-mode)
 | 
			
		||||
cd sparse-checkout-non-cone-mode
 | 
			
		||||
 | 
			
		||||
ENABLED=$(git config --local --get-all core.sparseCheckout)
 | 
			
		||||
 | 
			
		||||
if [ "$?" != "0" ]; then
 | 
			
		||||
    echo "Failed to verify that sparse-checkout is enabled"
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Check that sparse-checkout is enabled
 | 
			
		||||
if [ "$ENABLED" != "true" ]; then
 | 
			
		||||
  echo "Expected sparse-checkout to be enabled (is: $ENABLED)"
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
SPARSE_CHECKOUT_FILE=$(git rev-parse --git-path info/sparse-checkout)
 | 
			
		||||
 | 
			
		||||
if [ "$?" != "0" ]; then
 | 
			
		||||
    echo "Failed to validate sparse-checkout"
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Check that sparse-checkout list is not empty
 | 
			
		||||
if [ ! -f "$SPARSE_CHECKOUT_FILE" ]; then
 | 
			
		||||
  echo "Expected sparse-checkout file to exist"
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Check that all folders from sparse-checkout exists
 | 
			
		||||
for pattern in $(cat "$SPARSE_CHECKOUT_FILE")
 | 
			
		||||
do
 | 
			
		||||
  if [ ! -d "${pattern#/}" ]; then
 | 
			
		||||
    echo "Expected directory '${pattern#/}' to exist"
 | 
			
		||||
    exit 1
 | 
			
		||||
  fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
# Verify that the root directory is not checked out
 | 
			
		||||
if [ -f README.md ]; then
 | 
			
		||||
  echo "Expected top-level files not to exist"
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
@@ -1,63 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
# Verify .git folder
 | 
			
		||||
if [ ! -d "./sparse-checkout/.git" ]; then
 | 
			
		||||
  echo "Expected ./sparse-checkout/.git folder to exist"
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Verify sparse-checkout
 | 
			
		||||
cd sparse-checkout
 | 
			
		||||
 | 
			
		||||
SPARSE=$(git sparse-checkout list)
 | 
			
		||||
 | 
			
		||||
if [ "$?" != "0" ]; then
 | 
			
		||||
    echo "Failed to validate sparse-checkout"
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Check that sparse-checkout list is not empty
 | 
			
		||||
if [ -z "$SPARSE" ]; then
 | 
			
		||||
  echo "Expected sparse-checkout list to not be empty"
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Check that all folders of the sparse checkout exist
 | 
			
		||||
for pattern in $SPARSE
 | 
			
		||||
do
 | 
			
		||||
  if [ ! -d "$pattern" ]; then
 | 
			
		||||
    echo "Expected directory '$pattern' to exist"
 | 
			
		||||
    exit 1
 | 
			
		||||
  fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
checkSparse () {
 | 
			
		||||
  if [ ! -d "./$1" ]; then
 | 
			
		||||
    echo "Expected directory '$1' to exist"
 | 
			
		||||
    exit 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  for file in $(git ls-tree -r --name-only HEAD $1)
 | 
			
		||||
  do
 | 
			
		||||
    if [ ! -f "$file" ]; then
 | 
			
		||||
      echo "Expected file '$file' to exist"
 | 
			
		||||
      exit 1
 | 
			
		||||
    fi
 | 
			
		||||
  done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check that all folders and their children have been checked out
 | 
			
		||||
checkSparse __test__
 | 
			
		||||
checkSparse .github
 | 
			
		||||
checkSparse dist
 | 
			
		||||
 | 
			
		||||
# Check that only sparse-checkout folders have been checked out
 | 
			
		||||
for pattern in $(git ls-tree --name-only HEAD)
 | 
			
		||||
do
 | 
			
		||||
  if [ -d "$pattern" ]; then
 | 
			
		||||
    if [[ "$pattern" != "__test__" && "$pattern" != ".github" && "$pattern" != "dist" ]]; then
 | 
			
		||||
      echo "Expected directory '$pattern' to not exist"
 | 
			
		||||
      exit 1
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
done
 | 
			
		||||
@@ -53,15 +53,6 @@ inputs:
 | 
			
		||||
  clean:
 | 
			
		||||
    description: 'Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching'
 | 
			
		||||
    default: true
 | 
			
		||||
  sparse-checkout:
 | 
			
		||||
    description: >
 | 
			
		||||
      Do a sparse checkout on given patterns.
 | 
			
		||||
      Each pattern should be separated with new lines
 | 
			
		||||
    default: null
 | 
			
		||||
  sparse-checkout-cone-mode:
 | 
			
		||||
    description: >
 | 
			
		||||
      Specifies whether to use cone-mode when doing a sparse checkout.
 | 
			
		||||
    default: true
 | 
			
		||||
  fetch-depth:
 | 
			
		||||
    description: 'Number of commits to fetch. 0 indicates all history for all branches and tags.'
 | 
			
		||||
    default: 1
 | 
			
		||||
 
 | 
			
		||||
@@ -181,7 +181,7 @@ GITHUB_WORKSPACE=/home/runner/work/foo/foo
 | 
			
		||||
RUNNER_WORKSPACE=/home/runner/work/foo
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
V2 introduces a new constraint on the checkout path. The location must now be under `github.workspace`. Whereas the checkout@v1 constraint was one level up, under `runner.workspace`.
 | 
			
		||||
V2 introduces a new contraint on the checkout path. The location must now be under `github.workspace`. Whereas the checkout@v1 constraint was one level up, under `runner.workspace`.
 | 
			
		||||
 | 
			
		||||
V2 no longer changes `github.workspace` to follow wherever the self repo is checked-out.
 | 
			
		||||
 | 
			
		||||
@@ -287,4 +287,4 @@ Note:
 | 
			
		||||
- Update samples to consume `actions/checkout@v2`
 | 
			
		||||
- Job containers now require git in the PATH for checkout, otherwise fallback to REST API
 | 
			
		||||
- Minimum git version 2.18
 | 
			
		||||
- Update problem matcher logic regarding source file verification (runner)
 | 
			
		||||
- Update problem matcher logic regarding source file verification (runner)
 | 
			
		||||
							
								
								
									
										167
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										167
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							@@ -159,11 +159,11 @@ class GitAuthHelper {
 | 
			
		||||
        this.sshKeyPath = '';
 | 
			
		||||
        this.sshKnownHostsPath = '';
 | 
			
		||||
        this.temporaryHomePath = '';
 | 
			
		||||
        this.gitConfigPath = '';
 | 
			
		||||
        this.git = gitCommandManager;
 | 
			
		||||
        this.settings = gitSourceSettings || {};
 | 
			
		||||
        // Token auth header
 | 
			
		||||
        const serverUrl = urlHelper.getServerUrl(this.settings.githubServerUrl);
 | 
			
		||||
        this.tokenConfigKey = `http.${serverUrl.origin}/.extraheader`; // "origin" is SCHEME://HOSTNAME[:PORT]
 | 
			
		||||
        const basicCredential = Buffer.from(`x-access-token:${this.settings.authToken}`, 'utf8').toString('base64');
 | 
			
		||||
        core.setSecret(basicCredential);
 | 
			
		||||
        this.tokenPlaceholderConfigValue = `AUTHORIZATION: basic ***`;
 | 
			
		||||
@@ -181,15 +181,12 @@ class GitAuthHelper {
 | 
			
		||||
            yield this.removeAuth();
 | 
			
		||||
            // Configure new values
 | 
			
		||||
            yield this.configureSsh();
 | 
			
		||||
            yield this.configureCredentialsHelper();
 | 
			
		||||
            yield this.configureToken();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    configureTempGlobalConfig() {
 | 
			
		||||
        var _a, _b;
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            if (!!this.gitConfigPath) {
 | 
			
		||||
                return this.gitConfigPath;
 | 
			
		||||
            }
 | 
			
		||||
            // Already setup global config
 | 
			
		||||
            if (((_a = this.temporaryHomePath) === null || _a === void 0 ? void 0 : _a.length) > 0) {
 | 
			
		||||
                return path.join(this.temporaryHomePath, '.gitconfig');
 | 
			
		||||
@@ -202,7 +199,7 @@ class GitAuthHelper {
 | 
			
		||||
            yield fs.promises.mkdir(this.temporaryHomePath, { recursive: true });
 | 
			
		||||
            // Copy the global git config
 | 
			
		||||
            const gitConfigPath = path.join(process.env['HOME'] || os.homedir(), '.gitconfig');
 | 
			
		||||
            this.gitConfigPath = path.join(this.temporaryHomePath, '.gitconfig');
 | 
			
		||||
            const newGitConfigPath = path.join(this.temporaryHomePath, '.gitconfig');
 | 
			
		||||
            let configExists = false;
 | 
			
		||||
            try {
 | 
			
		||||
                yield fs.promises.stat(gitConfigPath);
 | 
			
		||||
@@ -214,31 +211,16 @@ class GitAuthHelper {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (configExists) {
 | 
			
		||||
                core.info(`Copying '${gitConfigPath}' to '${this.gitConfigPath}'`);
 | 
			
		||||
                yield io.cp(gitConfigPath, this.gitConfigPath);
 | 
			
		||||
                core.info(`Copying '${gitConfigPath}' to '${newGitConfigPath}'`);
 | 
			
		||||
                yield io.cp(gitConfigPath, newGitConfigPath);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                yield fs.promises.writeFile(this.gitConfigPath, '');
 | 
			
		||||
                yield fs.promises.writeFile(newGitConfigPath, '');
 | 
			
		||||
            }
 | 
			
		||||
            // Override HOME
 | 
			
		||||
            core.info(`Temporarily overriding HOME='${this.temporaryHomePath}' before making global git config changes`);
 | 
			
		||||
            this.git.setEnvironmentVariable('HOME', this.temporaryHomePath);
 | 
			
		||||
            return this.gitConfigPath;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    configureCredentialsHelper() {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            if (this.settings.lfs) {
 | 
			
		||||
                core.info(`lfs disabled, skipping custom credentials helper`);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            const newGitConfigPath = yield this.configureTempGlobalConfig();
 | 
			
		||||
            const credentialHelper = `
 | 
			
		||||
    [credential]
 | 
			
		||||
      helper = "!f() { echo username=x-access-token; echo password=${this.tokenConfigValue}; };f"
 | 
			
		||||
    `;
 | 
			
		||||
            core.info(`Configuring git to use a custom credential helper for aut to handle git lfs`);
 | 
			
		||||
            yield fs.promises.appendFile(newGitConfigPath, credentialHelper);
 | 
			
		||||
            return newGitConfigPath;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    configureGlobalAuth() {
 | 
			
		||||
@@ -247,6 +229,7 @@ class GitAuthHelper {
 | 
			
		||||
            const newGitConfigPath = yield this.configureTempGlobalConfig();
 | 
			
		||||
            try {
 | 
			
		||||
                // Configure the token
 | 
			
		||||
                yield this.configureToken(newGitConfigPath, true);
 | 
			
		||||
                // Configure HTTPS instead of SSH
 | 
			
		||||
                yield this.git.tryConfigUnset(this.insteadOfKey, true);
 | 
			
		||||
                if (!this.settings.sshKey) {
 | 
			
		||||
@@ -258,6 +241,7 @@ class GitAuthHelper {
 | 
			
		||||
            catch (err) {
 | 
			
		||||
                // Unset in case somehow written to the real global config
 | 
			
		||||
                core.info('Encountered an error when attempting to configure token. Attempting unconfigure.');
 | 
			
		||||
                yield this.git.tryConfigUnset(this.tokenConfigKey, true);
 | 
			
		||||
                throw err;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
@@ -272,7 +256,7 @@ class GitAuthHelper {
 | 
			
		||||
                // refer to https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing
 | 
			
		||||
                const output = yield this.git.submoduleForeach(
 | 
			
		||||
                // wrap the pipeline in quotes to make sure it's handled properly by submoduleForeach, rather than just the first part of the pipeline
 | 
			
		||||
                `sh -c "git config --local --show-origin --name-only --get-regexp remote.origin.url"`, this.settings.nestedSubmodules);
 | 
			
		||||
                `sh -c "git config --local '${this.tokenConfigKey}' '${this.tokenPlaceholderConfigValue}' && git config --local --show-origin --name-only --get-regexp remote.origin.url"`, this.settings.nestedSubmodules);
 | 
			
		||||
                // Replace the placeholder
 | 
			
		||||
                const configPaths = output.match(/(?<=(^|\n)file:)[^\t]+(?=\tremote\.origin\.url)/g) || [];
 | 
			
		||||
                for (const configPath of configPaths) {
 | 
			
		||||
@@ -295,6 +279,7 @@ class GitAuthHelper {
 | 
			
		||||
    removeAuth() {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            yield this.removeSsh();
 | 
			
		||||
            yield this.removeToken();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    removeGlobalConfig() {
 | 
			
		||||
@@ -364,6 +349,22 @@ class GitAuthHelper {
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    configureToken(configPath, globalConfig) {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            // Validate args
 | 
			
		||||
            assert.ok((configPath && globalConfig) || (!configPath && !globalConfig), 'Unexpected configureToken parameter combinations');
 | 
			
		||||
            // Default config path
 | 
			
		||||
            if (!configPath && !globalConfig) {
 | 
			
		||||
                configPath = path.join(this.git.getWorkingDirectory(), '.git', 'config');
 | 
			
		||||
            }
 | 
			
		||||
            // Configure a placeholder value. This approach avoids the credential being captured
 | 
			
		||||
            // by process creation audit events, which are commonly logged. For more information,
 | 
			
		||||
            // refer to https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing
 | 
			
		||||
            yield this.git.config(this.tokenConfigKey, this.tokenPlaceholderConfigValue, globalConfig);
 | 
			
		||||
            // Replace the placeholder
 | 
			
		||||
            yield this.replaceTokenPlaceholder(configPath || '');
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    replaceTokenPlaceholder(configPath) {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            assert.ok(configPath, 'configPath is not defined');
 | 
			
		||||
@@ -406,6 +407,12 @@ class GitAuthHelper {
 | 
			
		||||
            yield this.removeGitConfig(SSH_COMMAND_KEY);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    removeToken() {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            // HTTP extra header
 | 
			
		||||
            yield this.removeGitConfig(this.tokenConfigKey);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    removeGitConfig(configKey, submoduleOnly = false) {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            if (!submoduleOnly) {
 | 
			
		||||
@@ -463,7 +470,6 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
 | 
			
		||||
exports.createCommandManager = exports.MinimumGitVersion = void 0;
 | 
			
		||||
const core = __importStar(__nccwpck_require__(2186));
 | 
			
		||||
const exec = __importStar(__nccwpck_require__(1514));
 | 
			
		||||
const fs = __importStar(__nccwpck_require__(7147));
 | 
			
		||||
const fshelper = __importStar(__nccwpck_require__(7219));
 | 
			
		||||
const io = __importStar(__nccwpck_require__(7436));
 | 
			
		||||
const path = __importStar(__nccwpck_require__(1017));
 | 
			
		||||
@@ -474,9 +480,9 @@ const git_version_1 = __nccwpck_require__(3142);
 | 
			
		||||
// Auth header not supported before 2.9
 | 
			
		||||
// Wire protocol v2 not supported before 2.18
 | 
			
		||||
exports.MinimumGitVersion = new git_version_1.GitVersion('2.18');
 | 
			
		||||
function createCommandManager(workingDirectory, lfs, doSparseCheckout) {
 | 
			
		||||
function createCommandManager(workingDirectory, lfs) {
 | 
			
		||||
    return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
        return yield GitCommandManager.createCommandManager(workingDirectory, lfs, doSparseCheckout);
 | 
			
		||||
        return yield GitCommandManager.createCommandManager(workingDirectory, lfs);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
exports.createCommandManager = createCommandManager;
 | 
			
		||||
@@ -489,7 +495,6 @@ class GitCommandManager {
 | 
			
		||||
        };
 | 
			
		||||
        this.gitPath = '';
 | 
			
		||||
        this.lfs = false;
 | 
			
		||||
        this.doSparseCheckout = false;
 | 
			
		||||
        this.workingDirectory = '';
 | 
			
		||||
    }
 | 
			
		||||
    branchDelete(remote, branch) {
 | 
			
		||||
@@ -569,23 +574,6 @@ class GitCommandManager {
 | 
			
		||||
            return result;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    sparseCheckout(sparseCheckout) {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            yield this.execGit(['sparse-checkout', 'set', ...sparseCheckout]);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    sparseCheckoutNonConeMode(sparseCheckout) {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            yield this.execGit(['config', 'core.sparseCheckout', 'true']);
 | 
			
		||||
            const output = yield this.execGit([
 | 
			
		||||
                'rev-parse',
 | 
			
		||||
                '--git-path',
 | 
			
		||||
                'info/sparse-checkout'
 | 
			
		||||
            ]);
 | 
			
		||||
            const sparseCheckoutPath = path.join(this.workingDirectory, output.stdout.trimRight());
 | 
			
		||||
            yield fs.promises.appendFile(sparseCheckoutPath, `\n${sparseCheckout.join('\n')}\n`);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    checkout(ref, startPoint) {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            const args = ['checkout', '--progress', '--force'];
 | 
			
		||||
@@ -627,18 +615,15 @@ class GitCommandManager {
 | 
			
		||||
            return output.exitCode === 0;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    fetch(refSpec, options) {
 | 
			
		||||
    fetch(refSpec, fetchDepth) {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            const args = ['-c', 'protocol.version=2', 'fetch'];
 | 
			
		||||
            if (!refSpec.some(x => x === refHelper.tagsRefSpec)) {
 | 
			
		||||
                args.push('--no-tags');
 | 
			
		||||
            }
 | 
			
		||||
            args.push('--prune', '--progress', '--no-recurse-submodules');
 | 
			
		||||
            if (options.filter) {
 | 
			
		||||
                args.push(`--filter=${options.filter}`);
 | 
			
		||||
            }
 | 
			
		||||
            if (options.fetchDepth && options.fetchDepth > 0) {
 | 
			
		||||
                args.push(`--depth=${options.fetchDepth}`);
 | 
			
		||||
            if (fetchDepth && fetchDepth > 0) {
 | 
			
		||||
                args.push(`--depth=${fetchDepth}`);
 | 
			
		||||
            }
 | 
			
		||||
            else if (fshelper.fileExistsSync(path.join(this.workingDirectory, '.git', 'shallow'))) {
 | 
			
		||||
                args.push('--unshallow');
 | 
			
		||||
@@ -780,13 +765,6 @@ class GitCommandManager {
 | 
			
		||||
            yield this.execGit(args);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    submoduleStatus() {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            const output = yield this.execGit(['submodule', 'status'], true);
 | 
			
		||||
            core.debug(output.stdout);
 | 
			
		||||
            return output.exitCode === 0;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    tagExists(pattern) {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            const output = yield this.execGit(['tag', '--list', pattern]);
 | 
			
		||||
@@ -835,10 +813,10 @@ class GitCommandManager {
 | 
			
		||||
            return output.exitCode === 0;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    static createCommandManager(workingDirectory, lfs, doSparseCheckout) {
 | 
			
		||||
    static createCommandManager(workingDirectory, lfs) {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            const result = new GitCommandManager();
 | 
			
		||||
            yield result.initializeCommandManager(workingDirectory, lfs, doSparseCheckout);
 | 
			
		||||
            yield result.initializeCommandManager(workingDirectory, lfs);
 | 
			
		||||
            return result;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
@@ -874,7 +852,7 @@ class GitCommandManager {
 | 
			
		||||
            return result;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    initializeCommandManager(workingDirectory, lfs, doSparseCheckout) {
 | 
			
		||||
    initializeCommandManager(workingDirectory, lfs) {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            this.workingDirectory = workingDirectory;
 | 
			
		||||
            // Git-lfs will try to pull down assets if any of the local/user/system setting exist.
 | 
			
		||||
@@ -926,14 +904,6 @@ class GitCommandManager {
 | 
			
		||||
                    throw new Error(`Minimum required git-lfs version is ${minimumGitLfsVersion}. Your git-lfs ('${gitLfsPath}') is ${gitLfsVersion}`);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            this.doSparseCheckout = doSparseCheckout;
 | 
			
		||||
            if (this.doSparseCheckout) {
 | 
			
		||||
                // The `git sparse-checkout` command was introduced in Git v2.25.0
 | 
			
		||||
                const minimumGitSparseCheckoutVersion = new git_version_1.GitVersion('2.25');
 | 
			
		||||
                if (!gitVersion.checkMinimum(minimumGitSparseCheckoutVersion)) {
 | 
			
		||||
                    throw new Error(`Minimum Git version required for sparse checkout is ${minimumGitSparseCheckoutVersion}. Your git ('${this.gitPath}') is ${gitVersion}`);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            // Set the user agent
 | 
			
		||||
            const gitHttpUserAgent = `git/${gitVersion} (github-actions-checkout)`;
 | 
			
		||||
            core.debug(`Set git useragent to: ${gitHttpUserAgent}`);
 | 
			
		||||
@@ -1053,16 +1023,11 @@ function prepareExistingDirectory(git, repositoryPath, repositoryUrl, clean, ref
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                core.endGroup();
 | 
			
		||||
                // Check for submodules and delete any existing files if submodules are present
 | 
			
		||||
                if (!(yield git.submoduleStatus())) {
 | 
			
		||||
                    remove = true;
 | 
			
		||||
                    core.info('Bad Submodules found, removing existing files');
 | 
			
		||||
                }
 | 
			
		||||
                // Clean
 | 
			
		||||
                if (clean) {
 | 
			
		||||
                    core.startGroup('Cleaning the repository');
 | 
			
		||||
                    if (!(yield 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 further investigation, manually run 'git clean -ffdx' on the directory '${repositoryPath}'.`);
 | 
			
		||||
                        core.debug(`The clean command failed. This might be caused by: 1) path too long, 2) permission issue, or 3) file in use. For futher investigation, manually run 'git clean -ffdx' on the directory '${repositoryPath}'.`);
 | 
			
		||||
                        remove = true;
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (!(yield git.tryReset())) {
 | 
			
		||||
@@ -1233,24 +1198,20 @@ function getSource(settings) {
 | 
			
		||||
            }
 | 
			
		||||
            // Fetch
 | 
			
		||||
            core.startGroup('Fetching the repository');
 | 
			
		||||
            const fetchOptions = {};
 | 
			
		||||
            if (settings.sparseCheckout)
 | 
			
		||||
                fetchOptions.filter = 'blob:none';
 | 
			
		||||
            if (settings.fetchDepth <= 0) {
 | 
			
		||||
                // Fetch all branches and tags
 | 
			
		||||
                let refSpec = refHelper.getRefSpecForAllHistory(settings.ref, settings.commit);
 | 
			
		||||
                yield git.fetch(refSpec, fetchOptions);
 | 
			
		||||
                yield git.fetch(refSpec);
 | 
			
		||||
                // When all history is fetched, the ref we're interested in may have moved to a different
 | 
			
		||||
                // commit (push or force push). If so, fetch again with a targeted refspec.
 | 
			
		||||
                if (!(yield refHelper.testRef(git, settings.ref, settings.commit))) {
 | 
			
		||||
                    refSpec = refHelper.getRefSpec(settings.ref, settings.commit);
 | 
			
		||||
                    yield git.fetch(refSpec, fetchOptions);
 | 
			
		||||
                    yield git.fetch(refSpec);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                fetchOptions.fetchDepth = settings.fetchDepth;
 | 
			
		||||
                const refSpec = refHelper.getRefSpec(settings.ref, settings.commit);
 | 
			
		||||
                yield git.fetch(refSpec, fetchOptions);
 | 
			
		||||
                yield git.fetch(refSpec, settings.fetchDepth);
 | 
			
		||||
            }
 | 
			
		||||
            core.endGroup();
 | 
			
		||||
            // Checkout info
 | 
			
		||||
@@ -1260,23 +1221,11 @@ function getSource(settings) {
 | 
			
		||||
            // 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.
 | 
			
		||||
            // For sparse checkouts, let `checkout` fetch the needed objects lazily.
 | 
			
		||||
            if (settings.lfs && !settings.sparseCheckout) {
 | 
			
		||||
            if (settings.lfs) {
 | 
			
		||||
                core.startGroup('Fetching LFS objects');
 | 
			
		||||
                yield git.lfsFetch(checkoutInfo.startPoint || checkoutInfo.ref);
 | 
			
		||||
                core.endGroup();
 | 
			
		||||
            }
 | 
			
		||||
            // Sparse checkout
 | 
			
		||||
            if (settings.sparseCheckout) {
 | 
			
		||||
                core.startGroup('Setting up sparse checkout');
 | 
			
		||||
                if (settings.sparseCheckoutConeMode) {
 | 
			
		||||
                    yield git.sparseCheckout(settings.sparseCheckout);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    yield git.sparseCheckoutNonConeMode(settings.sparseCheckout);
 | 
			
		||||
                }
 | 
			
		||||
                core.endGroup();
 | 
			
		||||
            }
 | 
			
		||||
            // Checkout
 | 
			
		||||
            core.startGroup('Checking out the ref');
 | 
			
		||||
            yield git.checkout(checkoutInfo.ref, checkoutInfo.startPoint);
 | 
			
		||||
@@ -1330,7 +1279,7 @@ function cleanup(repositoryPath) {
 | 
			
		||||
        }
 | 
			
		||||
        let git;
 | 
			
		||||
        try {
 | 
			
		||||
            git = yield gitCommandManager.createCommandManager(repositoryPath, false, false);
 | 
			
		||||
            git = yield gitCommandManager.createCommandManager(repositoryPath, false);
 | 
			
		||||
        }
 | 
			
		||||
        catch (_a) {
 | 
			
		||||
            return;
 | 
			
		||||
@@ -1361,7 +1310,7 @@ function getGitCommandManager(settings) {
 | 
			
		||||
    return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
        core.info(`Working directory is '${settings.repositoryPath}'`);
 | 
			
		||||
        try {
 | 
			
		||||
            return yield gitCommandManager.createCommandManager(settings.repositoryPath, settings.lfs, settings.sparseCheckout != null);
 | 
			
		||||
            return yield gitCommandManager.createCommandManager(settings.repositoryPath, settings.lfs);
 | 
			
		||||
        }
 | 
			
		||||
        catch (err) {
 | 
			
		||||
            // Git is required for LFS
 | 
			
		||||
@@ -1504,7 +1453,6 @@ const path = __importStar(__nccwpck_require__(1017));
 | 
			
		||||
const retryHelper = __importStar(__nccwpck_require__(2155));
 | 
			
		||||
const toolCache = __importStar(__nccwpck_require__(7784));
 | 
			
		||||
const v4_1 = __importDefault(__nccwpck_require__(824));
 | 
			
		||||
const url_helper_1 = __nccwpck_require__(9437);
 | 
			
		||||
const IS_WINDOWS = process.platform === 'win32';
 | 
			
		||||
function downloadRepository(authToken, owner, repo, ref, commit, repositoryPath, baseUrl) {
 | 
			
		||||
    return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
@@ -1565,9 +1513,7 @@ function getDefaultBranch(authToken, owner, repo, baseUrl) {
 | 
			
		||||
        return yield retryHelper.execute(() => __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            var _a;
 | 
			
		||||
            core.info('Retrieving the default branch name');
 | 
			
		||||
            const octokit = github.getOctokit(authToken, {
 | 
			
		||||
                baseUrl: (0, url_helper_1.getServerApiUrl)(baseUrl)
 | 
			
		||||
            });
 | 
			
		||||
            const octokit = github.getOctokit(authToken, { baseUrl: baseUrl });
 | 
			
		||||
            let result;
 | 
			
		||||
            try {
 | 
			
		||||
                // Get the default branch from the repo info
 | 
			
		||||
@@ -1599,9 +1545,7 @@ function getDefaultBranch(authToken, owner, repo, baseUrl) {
 | 
			
		||||
exports.getDefaultBranch = getDefaultBranch;
 | 
			
		||||
function downloadArchive(authToken, owner, repo, ref, commit, baseUrl) {
 | 
			
		||||
    return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
        const octokit = github.getOctokit(authToken, {
 | 
			
		||||
            baseUrl: (0, url_helper_1.getServerApiUrl)(baseUrl)
 | 
			
		||||
        });
 | 
			
		||||
        const octokit = github.getOctokit(authToken, { baseUrl: baseUrl });
 | 
			
		||||
        const download = IS_WINDOWS
 | 
			
		||||
            ? octokit.rest.repos.downloadZipballArchive
 | 
			
		||||
            : octokit.rest.repos.downloadTarballArchive;
 | 
			
		||||
@@ -1712,15 +1656,6 @@ function getInputs() {
 | 
			
		||||
        // Clean
 | 
			
		||||
        result.clean = (core.getInput('clean') || 'true').toUpperCase() === 'TRUE';
 | 
			
		||||
        core.debug(`clean = ${result.clean}`);
 | 
			
		||||
        // Sparse checkout
 | 
			
		||||
        const sparseCheckout = core.getMultilineInput('sparse-checkout');
 | 
			
		||||
        if (sparseCheckout.length) {
 | 
			
		||||
            result.sparseCheckout = sparseCheckout;
 | 
			
		||||
            core.debug(`sparse checkout = ${result.sparseCheckout}`);
 | 
			
		||||
        }
 | 
			
		||||
        result.sparseCheckoutConeMode =
 | 
			
		||||
            (core.getInput('sparse-checkout-cone-mode') || 'true').toUpperCase() ===
 | 
			
		||||
                'TRUE';
 | 
			
		||||
        // Fetch depth
 | 
			
		||||
        result.fetchDepth = Math.floor(Number(core.getInput('fetch-depth') || '1'));
 | 
			
		||||
        if (isNaN(result.fetchDepth) || result.fetchDepth < 0) {
 | 
			
		||||
@@ -2091,7 +2026,7 @@ function checkCommitInfo(token, commitInfo, repositoryOwner, repositoryName, ref
 | 
			
		||||
            if (actualHeadSha !== expectedHeadSha) {
 | 
			
		||||
                core.debug(`Expected head sha ${expectedHeadSha}; actual head sha ${actualHeadSha}`);
 | 
			
		||||
                const octokit = github.getOctokit(token, {
 | 
			
		||||
                    baseUrl: (0, url_helper_1.getServerApiUrl)(baseUrl),
 | 
			
		||||
                    baseUrl: baseUrl,
 | 
			
		||||
                    userAgent: `actions-checkout-tracepoint/1.0 (code=STALE_MERGE;owner=${repositoryOwner};repo=${repositoryName};pr=${fromPayload('number')};run_id=${process.env['GITHUB_RUN_ID']};expected_head_sha=${expectedHeadSha};actual_head_sha=${actualHeadSha})`
 | 
			
		||||
                });
 | 
			
		||||
                yield octokit.rest.repos.get({
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -1,12 +1,12 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "checkout",
 | 
			
		||||
  "version": "3.5.3",
 | 
			
		||||
  "version": "3.6.0",
 | 
			
		||||
  "lockfileVersion": 2,
 | 
			
		||||
  "requires": true,
 | 
			
		||||
  "packages": {
 | 
			
		||||
    "": {
 | 
			
		||||
      "name": "checkout",
 | 
			
		||||
      "version": "3.5.3",
 | 
			
		||||
      "version": "3.6.0",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@actions/core": "^1.10.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "checkout",
 | 
			
		||||
  "version": "3.5.3",
 | 
			
		||||
  "version": "3.6.0",
 | 
			
		||||
  "description": "checkout action",
 | 
			
		||||
  "main": "lib/main.js",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,6 @@ export interface IGitAuthHelper {
 | 
			
		||||
  configureGlobalAuth(): Promise<void>
 | 
			
		||||
  configureSubmoduleAuth(): Promise<void>
 | 
			
		||||
  configureTempGlobalConfig(): Promise<string>
 | 
			
		||||
  configureCredentialsHelper(): Promise<void>
 | 
			
		||||
  removeAuth(): Promise<void>
 | 
			
		||||
  removeGlobalConfig(): Promise<void>
 | 
			
		||||
}
 | 
			
		||||
@@ -35,6 +34,7 @@ export function createAuthHelper(
 | 
			
		||||
class GitAuthHelper {
 | 
			
		||||
  private readonly git: IGitCommandManager
 | 
			
		||||
  private readonly settings: IGitSourceSettings
 | 
			
		||||
  private readonly tokenConfigKey: string
 | 
			
		||||
  private readonly tokenConfigValue: string
 | 
			
		||||
  private readonly tokenPlaceholderConfigValue: string
 | 
			
		||||
  private readonly insteadOfKey: string
 | 
			
		||||
@@ -43,7 +43,6 @@ class GitAuthHelper {
 | 
			
		||||
  private sshKeyPath = ''
 | 
			
		||||
  private sshKnownHostsPath = ''
 | 
			
		||||
  private temporaryHomePath = ''
 | 
			
		||||
  private gitConfigPath = ''
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    gitCommandManager: IGitCommandManager,
 | 
			
		||||
@@ -54,6 +53,7 @@ class GitAuthHelper {
 | 
			
		||||
 | 
			
		||||
    // Token auth header
 | 
			
		||||
    const serverUrl = urlHelper.getServerUrl(this.settings.githubServerUrl)
 | 
			
		||||
    this.tokenConfigKey = `http.${serverUrl.origin}/.extraheader` // "origin" is SCHEME://HOSTNAME[:PORT]
 | 
			
		||||
    const basicCredential = Buffer.from(
 | 
			
		||||
      `x-access-token:${this.settings.authToken}`,
 | 
			
		||||
      'utf8'
 | 
			
		||||
@@ -78,13 +78,10 @@ class GitAuthHelper {
 | 
			
		||||
 | 
			
		||||
    // Configure new values
 | 
			
		||||
    await this.configureSsh()
 | 
			
		||||
    await this.configureCredentialsHelper()
 | 
			
		||||
    await this.configureToken()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async configureTempGlobalConfig(): Promise<string> {
 | 
			
		||||
    if (!!this.gitConfigPath) {
 | 
			
		||||
      return this.gitConfigPath
 | 
			
		||||
    }
 | 
			
		||||
    // Already setup global config
 | 
			
		||||
    if (this.temporaryHomePath?.length > 0) {
 | 
			
		||||
      return path.join(this.temporaryHomePath, '.gitconfig')
 | 
			
		||||
@@ -101,7 +98,7 @@ class GitAuthHelper {
 | 
			
		||||
      process.env['HOME'] || os.homedir(),
 | 
			
		||||
      '.gitconfig'
 | 
			
		||||
    )
 | 
			
		||||
    this.gitConfigPath = path.join(this.temporaryHomePath, '.gitconfig')
 | 
			
		||||
    const newGitConfigPath = path.join(this.temporaryHomePath, '.gitconfig')
 | 
			
		||||
    let configExists = false
 | 
			
		||||
    try {
 | 
			
		||||
      await fs.promises.stat(gitConfigPath)
 | 
			
		||||
@@ -112,10 +109,10 @@ class GitAuthHelper {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (configExists) {
 | 
			
		||||
      core.info(`Copying '${gitConfigPath}' to '${this.gitConfigPath}'`)
 | 
			
		||||
      await io.cp(gitConfigPath, this.gitConfigPath)
 | 
			
		||||
      core.info(`Copying '${gitConfigPath}' to '${newGitConfigPath}'`)
 | 
			
		||||
      await io.cp(gitConfigPath, newGitConfigPath)
 | 
			
		||||
    } else {
 | 
			
		||||
      await fs.promises.writeFile(this.gitConfigPath, '')
 | 
			
		||||
      await fs.promises.writeFile(newGitConfigPath, '')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Override HOME
 | 
			
		||||
@@ -124,25 +121,7 @@ class GitAuthHelper {
 | 
			
		||||
    )
 | 
			
		||||
    this.git.setEnvironmentVariable('HOME', this.temporaryHomePath)
 | 
			
		||||
 | 
			
		||||
    return this.gitConfigPath
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async configureCredentialsHelper(): Promise<void> {
 | 
			
		||||
    if (this.settings.lfs) {
 | 
			
		||||
      core.info(`lfs disabled, skipping custom credentials helper`)
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    const newGitConfigPath = await this.configureTempGlobalConfig()
 | 
			
		||||
 | 
			
		||||
    const credentialHelper = `
 | 
			
		||||
    [credential]
 | 
			
		||||
      helper = "!f() { echo username=x-access-token; echo password=${this.tokenConfigValue}; };f"
 | 
			
		||||
    `
 | 
			
		||||
 | 
			
		||||
    core.info(
 | 
			
		||||
      `Configuring git to use a custom credential helper for aut to handle git lfs`
 | 
			
		||||
    )
 | 
			
		||||
    await fs.promises.appendFile(newGitConfigPath, credentialHelper)
 | 
			
		||||
    return newGitConfigPath
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async configureGlobalAuth(): Promise<void> {
 | 
			
		||||
@@ -150,6 +129,8 @@ class GitAuthHelper {
 | 
			
		||||
    const newGitConfigPath = await this.configureTempGlobalConfig()
 | 
			
		||||
    try {
 | 
			
		||||
      // Configure the token
 | 
			
		||||
      await this.configureToken(newGitConfigPath, true)
 | 
			
		||||
 | 
			
		||||
      // Configure HTTPS instead of SSH
 | 
			
		||||
      await this.git.tryConfigUnset(this.insteadOfKey, true)
 | 
			
		||||
      if (!this.settings.sshKey) {
 | 
			
		||||
@@ -162,6 +143,7 @@ class GitAuthHelper {
 | 
			
		||||
      core.info(
 | 
			
		||||
        'Encountered an error when attempting to configure token. Attempting unconfigure.'
 | 
			
		||||
      )
 | 
			
		||||
      await this.git.tryConfigUnset(this.tokenConfigKey, true)
 | 
			
		||||
      throw err
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -176,7 +158,7 @@ class GitAuthHelper {
 | 
			
		||||
      // refer to https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing
 | 
			
		||||
      const output = await this.git.submoduleForeach(
 | 
			
		||||
        // wrap the pipeline in quotes to make sure it's handled properly by submoduleForeach, rather than just the first part of the pipeline
 | 
			
		||||
        `sh -c "git config --local --show-origin --name-only --get-regexp remote.origin.url"`,
 | 
			
		||||
        `sh -c "git config --local '${this.tokenConfigKey}' '${this.tokenPlaceholderConfigValue}' && git config --local --show-origin --name-only --get-regexp remote.origin.url"`,
 | 
			
		||||
        this.settings.nestedSubmodules
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
@@ -208,6 +190,7 @@ class GitAuthHelper {
 | 
			
		||||
 | 
			
		||||
  async removeAuth(): Promise<void> {
 | 
			
		||||
    await this.removeSsh()
 | 
			
		||||
    await this.removeToken()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async removeGlobalConfig(): Promise<void> {
 | 
			
		||||
@@ -289,6 +272,34 @@ class GitAuthHelper {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async configureToken(
 | 
			
		||||
    configPath?: string,
 | 
			
		||||
    globalConfig?: boolean
 | 
			
		||||
  ): Promise<void> {
 | 
			
		||||
    // Validate args
 | 
			
		||||
    assert.ok(
 | 
			
		||||
      (configPath && globalConfig) || (!configPath && !globalConfig),
 | 
			
		||||
      'Unexpected configureToken parameter combinations'
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    // Default config path
 | 
			
		||||
    if (!configPath && !globalConfig) {
 | 
			
		||||
      configPath = path.join(this.git.getWorkingDirectory(), '.git', 'config')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Configure a placeholder value. This approach avoids the credential being captured
 | 
			
		||||
    // by process creation audit events, which are commonly logged. For more information,
 | 
			
		||||
    // refer to https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing
 | 
			
		||||
    await this.git.config(
 | 
			
		||||
      this.tokenConfigKey,
 | 
			
		||||
      this.tokenPlaceholderConfigValue,
 | 
			
		||||
      globalConfig
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    // Replace the placeholder
 | 
			
		||||
    await this.replaceTokenPlaceholder(configPath || '')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async replaceTokenPlaceholder(configPath: string): Promise<void> {
 | 
			
		||||
    assert.ok(configPath, 'configPath is not defined')
 | 
			
		||||
    let content = (await fs.promises.readFile(configPath)).toString()
 | 
			
		||||
@@ -334,6 +345,11 @@ class GitAuthHelper {
 | 
			
		||||
    await this.removeGitConfig(SSH_COMMAND_KEY)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async removeToken(): Promise<void> {
 | 
			
		||||
    // HTTP extra header
 | 
			
		||||
    await this.removeGitConfig(this.tokenConfigKey)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async removeGitConfig(
 | 
			
		||||
    configKey: string,
 | 
			
		||||
    submoduleOnly: boolean = false
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
import * as core from '@actions/core'
 | 
			
		||||
import * as exec from '@actions/exec'
 | 
			
		||||
import * as fs from 'fs'
 | 
			
		||||
import * as fshelper from './fs-helper'
 | 
			
		||||
import * as io from '@actions/io'
 | 
			
		||||
import * as path from 'path'
 | 
			
		||||
@@ -17,8 +16,6 @@ export interface IGitCommandManager {
 | 
			
		||||
  branchDelete(remote: boolean, branch: string): Promise<void>
 | 
			
		||||
  branchExists(remote: boolean, pattern: string): Promise<boolean>
 | 
			
		||||
  branchList(remote: boolean): Promise<string[]>
 | 
			
		||||
  sparseCheckout(sparseCheckout: string[]): Promise<void>
 | 
			
		||||
  sparseCheckoutNonConeMode(sparseCheckout: string[]): Promise<void>
 | 
			
		||||
  checkout(ref: string, startPoint: string): Promise<void>
 | 
			
		||||
  checkoutDetach(): Promise<void>
 | 
			
		||||
  config(
 | 
			
		||||
@@ -28,13 +25,7 @@ export interface IGitCommandManager {
 | 
			
		||||
    add?: boolean
 | 
			
		||||
  ): Promise<void>
 | 
			
		||||
  configExists(configKey: string, globalConfig?: boolean): Promise<boolean>
 | 
			
		||||
  fetch(
 | 
			
		||||
    refSpec: string[],
 | 
			
		||||
    options: {
 | 
			
		||||
      filter?: string
 | 
			
		||||
      fetchDepth?: number
 | 
			
		||||
    }
 | 
			
		||||
  ): Promise<void>
 | 
			
		||||
  fetch(refSpec: string[], fetchDepth?: number): Promise<void>
 | 
			
		||||
  getDefaultBranch(repositoryUrl: string): Promise<string>
 | 
			
		||||
  getWorkingDirectory(): string
 | 
			
		||||
  init(): Promise<void>
 | 
			
		||||
@@ -50,7 +41,6 @@ export interface IGitCommandManager {
 | 
			
		||||
  submoduleForeach(command: string, recursive: boolean): Promise<string>
 | 
			
		||||
  submoduleSync(recursive: boolean): Promise<void>
 | 
			
		||||
  submoduleUpdate(fetchDepth: number, recursive: boolean): Promise<void>
 | 
			
		||||
  submoduleStatus(): Promise<boolean>
 | 
			
		||||
  tagExists(pattern: string): Promise<boolean>
 | 
			
		||||
  tryClean(): Promise<boolean>
 | 
			
		||||
  tryConfigUnset(configKey: string, globalConfig?: boolean): Promise<boolean>
 | 
			
		||||
@@ -61,14 +51,9 @@ export interface IGitCommandManager {
 | 
			
		||||
 | 
			
		||||
export async function createCommandManager(
 | 
			
		||||
  workingDirectory: string,
 | 
			
		||||
  lfs: boolean,
 | 
			
		||||
  doSparseCheckout: boolean
 | 
			
		||||
  lfs: boolean
 | 
			
		||||
): Promise<IGitCommandManager> {
 | 
			
		||||
  return await GitCommandManager.createCommandManager(
 | 
			
		||||
    workingDirectory,
 | 
			
		||||
    lfs,
 | 
			
		||||
    doSparseCheckout
 | 
			
		||||
  )
 | 
			
		||||
  return await GitCommandManager.createCommandManager(workingDirectory, lfs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class GitCommandManager {
 | 
			
		||||
@@ -78,7 +63,6 @@ class GitCommandManager {
 | 
			
		||||
  }
 | 
			
		||||
  private gitPath = ''
 | 
			
		||||
  private lfs = false
 | 
			
		||||
  private doSparseCheckout = false
 | 
			
		||||
  private workingDirectory = ''
 | 
			
		||||
 | 
			
		||||
  // Private constructor; use createCommandManager()
 | 
			
		||||
@@ -169,27 +153,6 @@ class GitCommandManager {
 | 
			
		||||
    return result
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async sparseCheckout(sparseCheckout: string[]): Promise<void> {
 | 
			
		||||
    await this.execGit(['sparse-checkout', 'set', ...sparseCheckout])
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async sparseCheckoutNonConeMode(sparseCheckout: string[]): Promise<void> {
 | 
			
		||||
    await this.execGit(['config', 'core.sparseCheckout', 'true'])
 | 
			
		||||
    const output = await this.execGit([
 | 
			
		||||
      'rev-parse',
 | 
			
		||||
      '--git-path',
 | 
			
		||||
      'info/sparse-checkout'
 | 
			
		||||
    ])
 | 
			
		||||
    const sparseCheckoutPath = path.join(
 | 
			
		||||
      this.workingDirectory,
 | 
			
		||||
      output.stdout.trimRight()
 | 
			
		||||
    )
 | 
			
		||||
    await fs.promises.appendFile(
 | 
			
		||||
      sparseCheckoutPath,
 | 
			
		||||
      `\n${sparseCheckout.join('\n')}\n`
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async checkout(ref: string, startPoint: string): Promise<void> {
 | 
			
		||||
    const args = ['checkout', '--progress', '--force']
 | 
			
		||||
    if (startPoint) {
 | 
			
		||||
@@ -238,23 +201,15 @@ class GitCommandManager {
 | 
			
		||||
    return output.exitCode === 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async fetch(
 | 
			
		||||
    refSpec: string[],
 | 
			
		||||
    options: {filter?: string; fetchDepth?: number}
 | 
			
		||||
  ): Promise<void> {
 | 
			
		||||
  async fetch(refSpec: string[], fetchDepth?: number): Promise<void> {
 | 
			
		||||
    const args = ['-c', 'protocol.version=2', 'fetch']
 | 
			
		||||
    if (!refSpec.some(x => x === refHelper.tagsRefSpec)) {
 | 
			
		||||
      args.push('--no-tags')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    args.push('--prune', '--progress', '--no-recurse-submodules')
 | 
			
		||||
 | 
			
		||||
    if (options.filter) {
 | 
			
		||||
      args.push(`--filter=${options.filter}`)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (options.fetchDepth && options.fetchDepth > 0) {
 | 
			
		||||
      args.push(`--depth=${options.fetchDepth}`)
 | 
			
		||||
    if (fetchDepth && fetchDepth > 0) {
 | 
			
		||||
      args.push(`--depth=${fetchDepth}`)
 | 
			
		||||
    } else if (
 | 
			
		||||
      fshelper.fileExistsSync(
 | 
			
		||||
        path.join(this.workingDirectory, '.git', 'shallow')
 | 
			
		||||
@@ -402,12 +357,6 @@ class GitCommandManager {
 | 
			
		||||
    await this.execGit(args)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async submoduleStatus(): Promise<boolean> {
 | 
			
		||||
    const output = await this.execGit(['submodule', 'status'], true)
 | 
			
		||||
    core.debug(output.stdout)
 | 
			
		||||
    return output.exitCode === 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async tagExists(pattern: string): Promise<boolean> {
 | 
			
		||||
    const output = await this.execGit(['tag', '--list', pattern])
 | 
			
		||||
    return !!output.stdout.trim()
 | 
			
		||||
@@ -467,15 +416,10 @@ class GitCommandManager {
 | 
			
		||||
 | 
			
		||||
  static async createCommandManager(
 | 
			
		||||
    workingDirectory: string,
 | 
			
		||||
    lfs: boolean,
 | 
			
		||||
    doSparseCheckout: boolean
 | 
			
		||||
    lfs: boolean
 | 
			
		||||
  ): Promise<GitCommandManager> {
 | 
			
		||||
    const result = new GitCommandManager()
 | 
			
		||||
    await result.initializeCommandManager(
 | 
			
		||||
      workingDirectory,
 | 
			
		||||
      lfs,
 | 
			
		||||
      doSparseCheckout
 | 
			
		||||
    )
 | 
			
		||||
    await result.initializeCommandManager(workingDirectory, lfs)
 | 
			
		||||
    return result
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -525,8 +469,7 @@ class GitCommandManager {
 | 
			
		||||
 | 
			
		||||
  private async initializeCommandManager(
 | 
			
		||||
    workingDirectory: string,
 | 
			
		||||
    lfs: boolean,
 | 
			
		||||
    doSparseCheckout: boolean
 | 
			
		||||
    lfs: boolean
 | 
			
		||||
  ): Promise<void> {
 | 
			
		||||
    this.workingDirectory = workingDirectory
 | 
			
		||||
 | 
			
		||||
@@ -589,16 +532,6 @@ class GitCommandManager {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.doSparseCheckout = doSparseCheckout
 | 
			
		||||
    if (this.doSparseCheckout) {
 | 
			
		||||
      // The `git sparse-checkout` command was introduced in Git v2.25.0
 | 
			
		||||
      const minimumGitSparseCheckoutVersion = new GitVersion('2.25')
 | 
			
		||||
      if (!gitVersion.checkMinimum(minimumGitSparseCheckoutVersion)) {
 | 
			
		||||
        throw new Error(
 | 
			
		||||
          `Minimum Git version required for sparse checkout is ${minimumGitSparseCheckoutVersion}. Your git ('${this.gitPath}') is ${gitVersion}`
 | 
			
		||||
        )
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    // Set the user agent
 | 
			
		||||
    const gitHttpUserAgent = `git/${gitVersion} (github-actions-checkout)`
 | 
			
		||||
    core.debug(`Set git useragent to: ${gitHttpUserAgent}`)
 | 
			
		||||
 
 | 
			
		||||
@@ -81,18 +81,12 @@ export async function prepareExistingDirectory(
 | 
			
		||||
      }
 | 
			
		||||
      core.endGroup()
 | 
			
		||||
 | 
			
		||||
      // Check for submodules and delete any existing files if submodules are present
 | 
			
		||||
      if (!(await git.submoduleStatus())) {
 | 
			
		||||
        remove = true
 | 
			
		||||
        core.info('Bad Submodules found, removing existing files')
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Clean
 | 
			
		||||
      if (clean) {
 | 
			
		||||
        core.startGroup('Cleaning the repository')
 | 
			
		||||
        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 further investigation, manually run 'git clean -ffdx' on the directory '${repositoryPath}'.`
 | 
			
		||||
            `The clean command failed. This might be caused by: 1) path too long, 2) permission issue, or 3) file in use. For futher investigation, manually run 'git clean -ffdx' on the directory '${repositoryPath}'.`
 | 
			
		||||
          )
 | 
			
		||||
          remove = true
 | 
			
		||||
        } else if (!(await git.tryReset())) {
 | 
			
		||||
 
 | 
			
		||||
@@ -153,26 +153,23 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
 | 
			
		||||
 | 
			
		||||
    // Fetch
 | 
			
		||||
    core.startGroup('Fetching the repository')
 | 
			
		||||
    const fetchOptions: {filter?: string; fetchDepth?: number} = {}
 | 
			
		||||
    if (settings.sparseCheckout) fetchOptions.filter = 'blob:none'
 | 
			
		||||
    if (settings.fetchDepth <= 0) {
 | 
			
		||||
      // Fetch all branches and tags
 | 
			
		||||
      let refSpec = refHelper.getRefSpecForAllHistory(
 | 
			
		||||
        settings.ref,
 | 
			
		||||
        settings.commit
 | 
			
		||||
      )
 | 
			
		||||
      await git.fetch(refSpec, fetchOptions)
 | 
			
		||||
      await git.fetch(refSpec)
 | 
			
		||||
 | 
			
		||||
      // When all history is fetched, the ref we're interested in may have moved to a different
 | 
			
		||||
      // commit (push or force push). If so, fetch again with a targeted refspec.
 | 
			
		||||
      if (!(await refHelper.testRef(git, settings.ref, settings.commit))) {
 | 
			
		||||
        refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
 | 
			
		||||
        await git.fetch(refSpec, fetchOptions)
 | 
			
		||||
        await git.fetch(refSpec)
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      fetchOptions.fetchDepth = settings.fetchDepth
 | 
			
		||||
      const refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
 | 
			
		||||
      await git.fetch(refSpec, fetchOptions)
 | 
			
		||||
      await git.fetch(refSpec, settings.fetchDepth)
 | 
			
		||||
    }
 | 
			
		||||
    core.endGroup()
 | 
			
		||||
 | 
			
		||||
@@ -188,24 +185,12 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
 | 
			
		||||
    // 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.
 | 
			
		||||
    // For sparse checkouts, let `checkout` fetch the needed objects lazily.
 | 
			
		||||
    if (settings.lfs && !settings.sparseCheckout) {
 | 
			
		||||
    if (settings.lfs) {
 | 
			
		||||
      core.startGroup('Fetching LFS objects')
 | 
			
		||||
      await git.lfsFetch(checkoutInfo.startPoint || checkoutInfo.ref)
 | 
			
		||||
      core.endGroup()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Sparse checkout
 | 
			
		||||
    if (settings.sparseCheckout) {
 | 
			
		||||
      core.startGroup('Setting up sparse checkout')
 | 
			
		||||
      if (settings.sparseCheckoutConeMode) {
 | 
			
		||||
        await git.sparseCheckout(settings.sparseCheckout)
 | 
			
		||||
      } else {
 | 
			
		||||
        await git.sparseCheckoutNonConeMode(settings.sparseCheckout)
 | 
			
		||||
      }
 | 
			
		||||
      core.endGroup()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Checkout
 | 
			
		||||
    core.startGroup('Checking out the ref')
 | 
			
		||||
    await git.checkout(checkoutInfo.ref, checkoutInfo.startPoint)
 | 
			
		||||
@@ -276,11 +261,7 @@ export async function cleanup(repositoryPath: string): Promise<void> {
 | 
			
		||||
 | 
			
		||||
  let git: IGitCommandManager
 | 
			
		||||
  try {
 | 
			
		||||
    git = await gitCommandManager.createCommandManager(
 | 
			
		||||
      repositoryPath,
 | 
			
		||||
      false,
 | 
			
		||||
      false
 | 
			
		||||
    )
 | 
			
		||||
    git = await gitCommandManager.createCommandManager(repositoryPath, false)
 | 
			
		||||
  } catch {
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
@@ -316,8 +297,7 @@ async function getGitCommandManager(
 | 
			
		||||
  try {
 | 
			
		||||
    return await gitCommandManager.createCommandManager(
 | 
			
		||||
      settings.repositoryPath,
 | 
			
		||||
      settings.lfs,
 | 
			
		||||
      settings.sparseCheckout != null
 | 
			
		||||
      settings.lfs
 | 
			
		||||
    )
 | 
			
		||||
  } catch (err) {
 | 
			
		||||
    // Git is required for LFS
 | 
			
		||||
 
 | 
			
		||||
@@ -29,16 +29,6 @@ export interface IGitSourceSettings {
 | 
			
		||||
   */
 | 
			
		||||
  clean: boolean
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The array of folders to make the sparse checkout
 | 
			
		||||
   */
 | 
			
		||||
  sparseCheckout: string[]
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Indicates whether to use cone mode in the sparse checkout (if any)
 | 
			
		||||
   */
 | 
			
		||||
  sparseCheckoutConeMode: boolean
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The depth when fetching
 | 
			
		||||
   */
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@ import * as path from 'path'
 | 
			
		||||
import * as retryHelper from './retry-helper'
 | 
			
		||||
import * as toolCache from '@actions/tool-cache'
 | 
			
		||||
import {default as uuid} from 'uuid/v4'
 | 
			
		||||
import {getServerApiUrl} from './url-helper'
 | 
			
		||||
 | 
			
		||||
const IS_WINDOWS = process.platform === 'win32'
 | 
			
		||||
 | 
			
		||||
@@ -85,9 +84,7 @@ export async function getDefaultBranch(
 | 
			
		||||
): Promise<string> {
 | 
			
		||||
  return await retryHelper.execute(async () => {
 | 
			
		||||
    core.info('Retrieving the default branch name')
 | 
			
		||||
    const octokit = github.getOctokit(authToken, {
 | 
			
		||||
      baseUrl: getServerApiUrl(baseUrl)
 | 
			
		||||
    })
 | 
			
		||||
    const octokit = github.getOctokit(authToken, {baseUrl: baseUrl})
 | 
			
		||||
    let result: string
 | 
			
		||||
    try {
 | 
			
		||||
      // Get the default branch from the repo info
 | 
			
		||||
@@ -128,9 +125,7 @@ async function downloadArchive(
 | 
			
		||||
  commit: string,
 | 
			
		||||
  baseUrl?: string
 | 
			
		||||
): Promise<Buffer> {
 | 
			
		||||
  const octokit = github.getOctokit(authToken, {
 | 
			
		||||
    baseUrl: getServerApiUrl(baseUrl)
 | 
			
		||||
  })
 | 
			
		||||
  const octokit = github.getOctokit(authToken, {baseUrl: baseUrl})
 | 
			
		||||
  const download = IS_WINDOWS
 | 
			
		||||
    ? octokit.rest.repos.downloadZipballArchive
 | 
			
		||||
    : octokit.rest.repos.downloadTarballArchive
 | 
			
		||||
 
 | 
			
		||||
@@ -82,17 +82,6 @@ export async function getInputs(): Promise<IGitSourceSettings> {
 | 
			
		||||
  result.clean = (core.getInput('clean') || 'true').toUpperCase() === 'TRUE'
 | 
			
		||||
  core.debug(`clean = ${result.clean}`)
 | 
			
		||||
 | 
			
		||||
  // Sparse checkout
 | 
			
		||||
  const sparseCheckout = core.getMultilineInput('sparse-checkout')
 | 
			
		||||
  if (sparseCheckout.length) {
 | 
			
		||||
    result.sparseCheckout = sparseCheckout
 | 
			
		||||
    core.debug(`sparse checkout = ${result.sparseCheckout}`)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  result.sparseCheckoutConeMode =
 | 
			
		||||
    (core.getInput('sparse-checkout-cone-mode') || 'true').toUpperCase() ===
 | 
			
		||||
    'TRUE'
 | 
			
		||||
 | 
			
		||||
  // Fetch depth
 | 
			
		||||
  result.fetchDepth = Math.floor(Number(core.getInput('fetch-depth') || '1'))
 | 
			
		||||
  if (isNaN(result.fetchDepth) || result.fetchDepth < 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
import {IGitCommandManager} from './git-command-manager'
 | 
			
		||||
import * as core from '@actions/core'
 | 
			
		||||
import * as github from '@actions/github'
 | 
			
		||||
import {getServerApiUrl, isGhes} from './url-helper'
 | 
			
		||||
import {isGhes} from './url-helper'
 | 
			
		||||
 | 
			
		||||
export const tagsRefSpec = '+refs/tags/*:refs/tags/*'
 | 
			
		||||
 | 
			
		||||
@@ -245,7 +245,7 @@ export async function checkCommitInfo(
 | 
			
		||||
        `Expected head sha ${expectedHeadSha}; actual head sha ${actualHeadSha}`
 | 
			
		||||
      )
 | 
			
		||||
      const octokit = github.getOctokit(token, {
 | 
			
		||||
        baseUrl: getServerApiUrl(baseUrl),
 | 
			
		||||
        baseUrl: baseUrl,
 | 
			
		||||
        userAgent: `actions-checkout-tracepoint/1.0 (code=STALE_MERGE;owner=${repositoryOwner};repo=${repositoryName};pr=${fromPayload(
 | 
			
		||||
          'number'
 | 
			
		||||
        )};run_id=${
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user