in paths-filter/src/git.ts [54:133]
export async function getChangesSinceMergeBase(base: string, head: string, initialFetchDepth: number): Promise<File[]> {
let baseRef: string | undefined
let headRef: string | undefined
async function hasMergeBase(): Promise<boolean> {
if (baseRef === undefined || headRef === undefined) {
return false
}
return (await getExecOutput('git', ['merge-base', baseRef, headRef], {ignoreReturnCode: true})).exitCode === 0
}
let noMergeBase = false
core.startGroup(`Searching for merge-base ${base}...${head}`)
try {
baseRef = await getLocalRef(base)
headRef = await getLocalRef(head)
if (!(await hasMergeBase())) {
await getExecOutput('git', ['fetch', '--no-tags', `--depth=${initialFetchDepth}`, 'origin', base, head])
if (baseRef === undefined || headRef === undefined) {
baseRef = baseRef ?? (await getLocalRef(base))
headRef = headRef ?? (await getLocalRef(head))
if (baseRef === undefined || headRef === undefined) {
await getExecOutput('git', ['fetch', '--tags', '--depth=1', 'origin', base, head], {
ignoreReturnCode: true // returns exit code 1 if tags on remote were updated - we can safely ignore it
})
baseRef = baseRef ?? (await getLocalRef(base))
headRef = headRef ?? (await getLocalRef(head))
if (baseRef === undefined) {
throw new Error(
`Could not determine what is ${base} - fetch works but it's not a branch, tag or commit SHA`
)
}
if (headRef === undefined) {
throw new Error(
`Could not determine what is ${head} - fetch works but it's not a branch, tag or commit SHA`
)
}
}
}
let depth = initialFetchDepth
let lastCommitCount = await getCommitCount()
while (!(await hasMergeBase())) {
depth = Math.min(depth * 2, Number.MAX_SAFE_INTEGER)
await getExecOutput('git', ['fetch', `--deepen=${depth}`, 'origin', base, head])
const commitCount = await getCommitCount()
if (commitCount === lastCommitCount) {
core.info('No more commits were fetched')
core.info('Last attempt will be to fetch full history')
await getExecOutput('git', ['fetch'])
if (!(await hasMergeBase())) {
noMergeBase = true
}
break
}
lastCommitCount = commitCount
}
}
} finally {
core.endGroup()
}
// Three dots '...' change detection - finds merge-base and compares against it
let diffArg = `${baseRef}...${headRef}`
if (noMergeBase) {
core.warning('No merge base found - change detection will use direct <commit>..<commit> comparison')
diffArg = `${baseRef}..${headRef}`
}
// Get changes introduced on ref compared to base
core.startGroup(`Change detection ${diffArg}`)
let output = ''
try {
output = (await getExecOutput('git', ['diff', '--no-renames', '--name-status', '-z', diffArg])).stdout
} finally {
fixStdOutNullTermination()
core.endGroup()
}
return parseGitDiffOutput(output)
}