mirror of
				https://github.com/actions/checkout.git
				synced 2025-11-01 02:44:19 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			126 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import * as assert from 'assert'
 | |
| import * as core from '@actions/core'
 | |
| import * as fs from 'fs'
 | |
| import * as fsHelper from './fs-helper'
 | |
| import * as io from '@actions/io'
 | |
| import * as path from 'path'
 | |
| import {IGitCommandManager} from './git-command-manager'
 | |
| 
 | |
| export async function prepareExistingDirectory(
 | |
|   git: IGitCommandManager | undefined,
 | |
|   repositoryPath: string,
 | |
|   repositoryUrl: string,
 | |
|   clean: boolean,
 | |
|   ref: string
 | |
| ): Promise<void> {
 | |
|   assert.ok(repositoryPath, 'Expected repositoryPath to be defined')
 | |
|   assert.ok(repositoryUrl, 'Expected repositoryUrl to be defined')
 | |
| 
 | |
|   // Indicates whether to delete the directory contents
 | |
|   let remove = false
 | |
| 
 | |
|   // Check whether using git or REST API
 | |
|   if (!git) {
 | |
|     remove = true
 | |
|   }
 | |
|   // Fetch URL does not match
 | |
|   else if (
 | |
|     !fsHelper.directoryExistsSync(path.join(repositoryPath, '.git')) ||
 | |
|     repositoryUrl !== (await git.tryGetFetchUrl())
 | |
|   ) {
 | |
|     remove = true
 | |
|   } else {
 | |
|     // 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 as any)?.message ?? error}`
 | |
|         )
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     try {
 | |
|       core.startGroup('Removing previously created refs, to avoid conflicts')
 | |
|       // 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 any conflicting refs/remotes/origin/*
 | |
|       // Example 1: Consider ref is refs/heads/foo and previously fetched refs/remotes/origin/foo/bar
 | |
|       // Example 2: Consider ref is refs/heads/foo/bar and previously fetched refs/remotes/origin/foo
 | |
|       if (ref) {
 | |
|         ref = ref.startsWith('refs/') ? ref : `refs/heads/${ref}`
 | |
|         if (ref.startsWith('refs/heads/')) {
 | |
|           const upperName1 = ref.toUpperCase().substr('REFS/HEADS/'.length)
 | |
|           const upperName1Slash = `${upperName1}/`
 | |
|           branches = await git.branchList(true)
 | |
|           for (const branch of branches) {
 | |
|             const upperName2 = branch.substr('origin/'.length).toUpperCase()
 | |
|             const upperName2Slash = `${upperName2}/`
 | |
|             if (
 | |
|               upperName1.startsWith(upperName2Slash) ||
 | |
|               upperName2.startsWith(upperName1Slash)
 | |
|             ) {
 | |
|               await git.branchDelete(true, branch)
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       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}'.`
 | |
|           )
 | |
|           remove = true
 | |
|         } else if (!(await git.tryReset())) {
 | |
|           remove = true
 | |
|         }
 | |
|         core.endGroup()
 | |
| 
 | |
|         if (remove) {
 | |
|           core.warning(
 | |
|             `Unable to clean or reset the repository. The repository will be recreated instead.`
 | |
|           )
 | |
|         }
 | |
|       }
 | |
|     } catch (error) {
 | |
|       core.warning(
 | |
|         `Unable to prepare the existing repository. The repository will be recreated instead.`
 | |
|       )
 | |
|       remove = true
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (remove) {
 | |
|     // Delete the contents of the directory. Don't delete the directory itself
 | |
|     // since it might be the current working directory.
 | |
|     core.info(`Deleting the contents of '${repositoryPath}'`)
 | |
|     for (const file of await fs.promises.readdir(repositoryPath)) {
 | |
|       await io.rmRF(path.join(repositoryPath, file))
 | |
|     }
 | |
|   }
 | |
| }
 | 
