mirror of
https://github.com/actions/checkout.git
synced 2026-05-25 05:30:23 +00:00
Fix checkout init for SHA-256 repositories
This commit is contained in:
@@ -15,6 +15,11 @@ import {GitVersion} from './git-version'
|
||||
export const MinimumGitVersion = new GitVersion('2.18')
|
||||
export const MinimumGitSparseCheckoutVersion = new GitVersion('2.28')
|
||||
|
||||
export interface GitObjectFormatResult {
|
||||
format: string
|
||||
succeeded: boolean
|
||||
}
|
||||
|
||||
export interface IGitCommandManager {
|
||||
branchDelete(remote: boolean, branch: string): Promise<void>
|
||||
branchExists(remote: boolean, pattern: string): Promise<boolean>
|
||||
@@ -43,7 +48,7 @@ export interface IGitCommandManager {
|
||||
getDefaultBranch(repositoryUrl: string): Promise<string>
|
||||
getSubmoduleConfigPaths(recursive: boolean): Promise<string[]>
|
||||
getWorkingDirectory(): string
|
||||
init(): Promise<void>
|
||||
init(objectFormat?: string): Promise<void>
|
||||
isDetached(): Promise<boolean>
|
||||
lfsFetch(ref: string): Promise<void>
|
||||
lfsInstall(): Promise<void>
|
||||
@@ -68,6 +73,7 @@ export interface IGitCommandManager {
|
||||
): Promise<boolean>
|
||||
tryDisableAutomaticGarbageCollection(): Promise<boolean>
|
||||
tryGetFetchUrl(): Promise<string>
|
||||
tryGetObjectFormat(repositoryUrl: string): Promise<GitObjectFormatResult>
|
||||
tryGetConfigValues(
|
||||
configKey: string,
|
||||
globalConfig?: boolean,
|
||||
@@ -364,8 +370,14 @@ class GitCommandManager {
|
||||
return this.workingDirectory
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
await this.execGit(['init', this.workingDirectory])
|
||||
async init(objectFormat?: string): Promise<void> {
|
||||
const args = ['init']
|
||||
if (objectFormat === 'sha256') {
|
||||
args.push('--object-format=sha256')
|
||||
}
|
||||
args.push(this.workingDirectory)
|
||||
|
||||
await this.execGit(args)
|
||||
}
|
||||
|
||||
async isDetached(): Promise<boolean> {
|
||||
@@ -536,6 +548,55 @@ class GitCommandManager {
|
||||
return stdout
|
||||
}
|
||||
|
||||
async tryGetObjectFormat(
|
||||
repositoryUrl: string
|
||||
): Promise<GitObjectFormatResult> {
|
||||
try {
|
||||
const output = await this.execGit(
|
||||
[
|
||||
'-c',
|
||||
'protocol.version=2',
|
||||
'ls-remote',
|
||||
'--quiet',
|
||||
'--exit-code',
|
||||
'--symref',
|
||||
repositoryUrl,
|
||||
'HEAD'
|
||||
],
|
||||
true,
|
||||
true
|
||||
)
|
||||
|
||||
if (output.exitCode !== 0) {
|
||||
core.debug(
|
||||
`Unable to determine repository object format: git ls-remote exited with ${output.exitCode}`
|
||||
)
|
||||
return {format: '', succeeded: false}
|
||||
}
|
||||
|
||||
for (const line of output.stdout.trim().split('\n')) {
|
||||
const [oid, ref] = line.split('\t')
|
||||
if (ref !== 'HEAD') {
|
||||
continue
|
||||
}
|
||||
if (/^[0-9a-fA-F]{64}$/.test(oid)) {
|
||||
return {format: 'sha256', succeeded: true}
|
||||
}
|
||||
if (/^[0-9a-fA-F]{40}$/.test(oid)) {
|
||||
return {format: 'sha1', succeeded: true}
|
||||
}
|
||||
}
|
||||
|
||||
core.debug('Unable to determine repository object format from HEAD')
|
||||
return {format: '', succeeded: false}
|
||||
} catch (err) {
|
||||
core.debug(
|
||||
`Unable to determine repository object format: ${(err as any)?.message ?? err}`
|
||||
)
|
||||
return {format: '', succeeded: false}
|
||||
}
|
||||
}
|
||||
|
||||
async tryGetConfigValues(
|
||||
configKey: string,
|
||||
globalConfig?: boolean,
|
||||
|
||||
@@ -105,12 +105,36 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
||||
// Save state for POST action
|
||||
stateHelper.setRepositoryPath(settings.repositoryPath)
|
||||
|
||||
let defaultBranch = ''
|
||||
|
||||
// Initialize the repository
|
||||
if (
|
||||
!fsHelper.directoryExistsSync(path.join(settings.repositoryPath, '.git'))
|
||||
) {
|
||||
core.startGroup('Determining repository object format')
|
||||
let objectFormatResult =
|
||||
await githubApiHelper.tryGetRepositoryObjectFormat(
|
||||
settings.authToken,
|
||||
settings.repositoryOwner,
|
||||
settings.repositoryName,
|
||||
settings.githubServerUrl,
|
||||
settings.ref,
|
||||
settings.commit
|
||||
)
|
||||
if (!objectFormatResult.succeeded) {
|
||||
objectFormatResult = await git.tryGetObjectFormat(repositoryUrl)
|
||||
}
|
||||
const objectFormat = objectFormatResult.succeeded
|
||||
? objectFormatResult.format
|
||||
: ''
|
||||
defaultBranch = objectFormatResult.defaultBranch || ''
|
||||
if (objectFormat === 'sha256') {
|
||||
core.info('Detected SHA-256 repository object format')
|
||||
}
|
||||
core.endGroup()
|
||||
|
||||
core.startGroup('Initializing the repository')
|
||||
await git.init()
|
||||
await git.init(objectFormat)
|
||||
await git.remoteAdd('origin', repositoryUrl)
|
||||
core.endGroup()
|
||||
}
|
||||
@@ -138,6 +162,9 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
||||
core.startGroup('Determining the default branch')
|
||||
if (settings.sshKey) {
|
||||
settings.ref = await git.getDefaultBranch(repositoryUrl)
|
||||
} else if (defaultBranch) {
|
||||
core.info(`Default branch '${defaultBranch}'`)
|
||||
settings.ref = `refs/heads/${defaultBranch}`
|
||||
} else {
|
||||
settings.ref = await githubApiHelper.getDefaultBranch(
|
||||
settings.authToken,
|
||||
|
||||
@@ -11,6 +11,12 @@ import {getServerApiUrl} from './url-helper'
|
||||
|
||||
const IS_WINDOWS = process.platform === 'win32'
|
||||
|
||||
export interface RepositoryObjectFormatResult {
|
||||
defaultBranch?: string
|
||||
format: string
|
||||
succeeded: boolean
|
||||
}
|
||||
|
||||
export async function downloadRepository(
|
||||
authToken: string,
|
||||
owner: string,
|
||||
@@ -122,6 +128,84 @@ export async function getDefaultBranch(
|
||||
})
|
||||
}
|
||||
|
||||
export async function tryGetRepositoryObjectFormat(
|
||||
authToken: string,
|
||||
owner: string,
|
||||
repo: string,
|
||||
baseUrl?: string,
|
||||
ref?: string,
|
||||
commit?: string
|
||||
): Promise<RepositoryObjectFormatResult> {
|
||||
try {
|
||||
const commitFormat = getObjectFormat(commit)
|
||||
if (commitFormat) {
|
||||
return {format: commitFormat, succeeded: true}
|
||||
}
|
||||
|
||||
const octokit = github.getOctokit(authToken, {
|
||||
baseUrl: getServerApiUrl(baseUrl)
|
||||
})
|
||||
|
||||
let branchName = getBranchName(ref)
|
||||
let defaultBranch = ''
|
||||
if (!branchName) {
|
||||
const repository = await octokit.rest.repos.get({owner, repo})
|
||||
defaultBranch = repository.data.default_branch
|
||||
assert.ok(defaultBranch, 'default_branch cannot be empty')
|
||||
branchName = defaultBranch
|
||||
}
|
||||
|
||||
const branch = await octokit.rest.repos.getBranch({
|
||||
owner,
|
||||
repo,
|
||||
branch: branchName
|
||||
})
|
||||
const branchFormat = getObjectFormat(branch.data.commit.sha)
|
||||
if (branchFormat) {
|
||||
return {
|
||||
defaultBranch: defaultBranch || undefined,
|
||||
format: branchFormat,
|
||||
succeeded: true
|
||||
}
|
||||
}
|
||||
|
||||
core.debug('Unable to determine repository object format from commit SHA')
|
||||
return {format: '', succeeded: false}
|
||||
} catch (err) {
|
||||
core.debug(
|
||||
`Unable to determine repository object format: ${(err as any)?.message ?? err}`
|
||||
)
|
||||
return {format: '', succeeded: false}
|
||||
}
|
||||
}
|
||||
|
||||
function getBranchName(ref?: string): string {
|
||||
if (!ref) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const headsPrefix = 'refs/heads/'
|
||||
if (ref.startsWith(headsPrefix)) {
|
||||
return ref.substring(headsPrefix.length)
|
||||
}
|
||||
|
||||
if (!ref.startsWith('refs/') && !getObjectFormat(ref)) {
|
||||
return ref
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
function getObjectFormat(sha?: string): string {
|
||||
if (/^[0-9a-fA-F]{64}$/.test(sha || '')) {
|
||||
return 'sha256'
|
||||
}
|
||||
if (/^[0-9a-fA-F]{40}$/.test(sha || '')) {
|
||||
return 'sha1'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
async function downloadArchive(
|
||||
authToken: string,
|
||||
owner: string,
|
||||
|
||||
Reference in New Issue
Block a user