From 0c0d1a854affba7773441ee8505d51befcca4c59 Mon Sep 17 00:00:00 2001 From: Michal Dorner Date: Tue, 9 Mar 2021 21:13:57 +0100 Subject: [PATCH 1/4] Fetch base and search merge-base without creating local branch --- dist/index.js | 21 +++++++++++---------- src/git.ts | 22 ++++++++++------------ src/main.ts | 4 ++-- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/dist/index.js b/dist/index.js index 71893ad6..b9fb2405 100644 --- a/dist/index.js +++ b/dist/index.js @@ -3865,29 +3865,30 @@ async function getChangesOnHead() { return parseGitDiffOutput(output); } exports.getChangesOnHead = getChangesOnHead; -async function getChangesSinceMergeBase(baseRef, ref, initialFetchDepth) { +async function getChangesSinceMergeBase(base, initialFetchDepth) { + const baseRef = `remotes/origin/${base}`; async function hasMergeBase() { - return (await exec_1.default('git', ['merge-base', baseRef, ref], { ignoreReturnCode: true })).code === 0; + return (await exec_1.default('git', ['merge-base', baseRef, exports.HEAD], { ignoreReturnCode: true })).code === 0; } let noMergeBase = false; - core.startGroup(`Searching for merge-base ${baseRef}...${ref}`); + core.startGroup(`Searching for merge-base ${baseRef}...${exports.HEAD}`); try { let init = true; let lastCommitCount = await getCommitCount(); let depth = Math.max(lastCommitCount * 2, initialFetchDepth); while (!(await hasMergeBase())) { if (init) { - await exec_1.default('git', ['fetch', `--depth=${depth}`, 'origin', `${baseRef}:${baseRef}`, `${ref}`]); + await exec_1.default('git', ['fetch', `--depth=${depth}`, 'origin', base, exports.HEAD]); init = false; } else { - await exec_1.default('git', ['fetch', `--deepen=${depth}`, 'origin', baseRef, ref]); + await exec_1.default('git', ['fetch', `--deepen=${depth}`, 'origin', base, exports.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 exec_1.default('git', ['fetch', '--unshallow']); + await exec_1.default('git', ['fetch']); if (!(await hasMergeBase())) { noMergeBase = true; } @@ -3905,11 +3906,11 @@ async function getChangesSinceMergeBase(baseRef, ref, initialFetchDepth) { return await listAllFilesAsAdded(); } // Get changes introduced on HEAD compared to ref - core.startGroup(`Change detection ${baseRef}...${ref}`); + core.startGroup(`Change detection ${baseRef}...${exports.HEAD}`); let output = ''; try { // Three dots '...' change detection - finds merge-base and compares against it - output = (await exec_1.default('git', ['diff', '--no-renames', '--name-status', '-z', `${baseRef}...${ref}`])).stdout; + output = (await exec_1.default('git', ['diff', '--no-renames', '--name-status', '-z', `${baseRef}...${exports.HEAD}`])).stdout; } finally { fixStdOutNullTermination(); @@ -4735,7 +4736,7 @@ async function getChangedFilesFromGit(base, initialFetchDepth) { if (baseSha === git.NULL_SHA) { if (defaultRef && baseRef !== defaultRef) { core.info(`First push of a branch detected - changes will be detected against the default branch ${defaultRef}`); - return await git.getChangesSinceMergeBase(defaultRef, ref, initialFetchDepth); + return await git.getChangesSinceMergeBase(defaultRef, initialFetchDepth); } else { core.info('Initial push detected - all files will be listed as added'); @@ -4747,7 +4748,7 @@ async function getChangedFilesFromGit(base, initialFetchDepth) { } // Changes introduced by current branch against the base branch core.info(`Changes will be detected against the branch ${baseRef}`); - return await git.getChangesSinceMergeBase(baseRef, ref, initialFetchDepth); + return await git.getChangesSinceMergeBase(baseRef, initialFetchDepth); } // Uses github REST api to get list of files changed in PR async function getChangedFilesFromApi(token, pullRequest) { diff --git a/src/git.ts b/src/git.ts index a55faa6b..b31dedf2 100644 --- a/src/git.ts +++ b/src/git.ts @@ -54,33 +54,31 @@ export async function getChangesOnHead(): Promise { return parseGitDiffOutput(output) } -export async function getChangesSinceMergeBase( - baseRef: string, - ref: string, - initialFetchDepth: number -): Promise { +export async function getChangesSinceMergeBase(base: string, initialFetchDepth: number): Promise { + const baseRef = `remotes/origin/${base}` + async function hasMergeBase(): Promise { - return (await exec('git', ['merge-base', baseRef, ref], {ignoreReturnCode: true})).code === 0 + return (await exec('git', ['merge-base', baseRef, HEAD], {ignoreReturnCode: true})).code === 0 } let noMergeBase = false - core.startGroup(`Searching for merge-base ${baseRef}...${ref}`) + core.startGroup(`Searching for merge-base ${baseRef}...${HEAD}`) try { let init = true let lastCommitCount = await getCommitCount() let depth = Math.max(lastCommitCount * 2, initialFetchDepth) while (!(await hasMergeBase())) { if (init) { - await exec('git', ['fetch', `--depth=${depth}`, 'origin', `${baseRef}:${baseRef}`, `${ref}`]) + await exec('git', ['fetch', `--depth=${depth}`, 'origin', base, HEAD]) init = false } else { - await exec('git', ['fetch', `--deepen=${depth}`, 'origin', baseRef, ref]) + await exec('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 exec('git', ['fetch', '--unshallow']) + await exec('git', ['fetch']) if (!(await hasMergeBase())) { noMergeBase = true } @@ -99,11 +97,11 @@ export async function getChangesSinceMergeBase( } // Get changes introduced on HEAD compared to ref - core.startGroup(`Change detection ${baseRef}...${ref}`) + core.startGroup(`Change detection ${baseRef}...${HEAD}`) let output = '' try { // Three dots '...' change detection - finds merge-base and compares against it - output = (await exec('git', ['diff', '--no-renames', '--name-status', '-z', `${baseRef}...${ref}`])).stdout + output = (await exec('git', ['diff', '--no-renames', '--name-status', '-z', `${baseRef}...${HEAD}`])).stdout } finally { fixStdOutNullTermination() core.endGroup() diff --git a/src/main.ts b/src/main.ts index e3d6ebc4..d9077963 100644 --- a/src/main.ts +++ b/src/main.ts @@ -109,7 +109,7 @@ async function getChangedFilesFromGit(base: string, initialFetchDepth: number): if (baseSha === git.NULL_SHA) { if (defaultRef && baseRef !== defaultRef) { core.info(`First push of a branch detected - changes will be detected against the default branch ${defaultRef}`) - return await git.getChangesSinceMergeBase(defaultRef, ref, initialFetchDepth) + return await git.getChangesSinceMergeBase(defaultRef, initialFetchDepth) } else { core.info('Initial push detected - all files will be listed as added') return await git.listAllFilesAsAdded() @@ -122,7 +122,7 @@ async function getChangedFilesFromGit(base: string, initialFetchDepth: number): // Changes introduced by current branch against the base branch core.info(`Changes will be detected against the branch ${baseRef}`) - return await git.getChangesSinceMergeBase(baseRef, ref, initialFetchDepth) + return await git.getChangesSinceMergeBase(baseRef, initialFetchDepth) } // Uses github REST api to get list of files changed in PR From a301a0ad83560422b6c956dc419bb6e2afa7b72f Mon Sep 17 00:00:00 2001 From: Michal Dorner Date: Tue, 9 Mar 2021 21:44:15 +0100 Subject: [PATCH 2/4] Refactor getChangesSinceMergeBase() code --- dist/index.js | 36 ++++++++++++++++-------------------- src/git.ts | 35 ++++++++++++++++------------------- 2 files changed, 32 insertions(+), 39 deletions(-) diff --git a/dist/index.js b/dist/index.js index b9fb2405..44274fb1 100644 --- a/dist/index.js +++ b/dist/index.js @@ -3873,29 +3873,25 @@ async function getChangesSinceMergeBase(base, initialFetchDepth) { let noMergeBase = false; core.startGroup(`Searching for merge-base ${baseRef}...${exports.HEAD}`); try { - let init = true; - let lastCommitCount = await getCommitCount(); - let depth = Math.max(lastCommitCount * 2, initialFetchDepth); - while (!(await hasMergeBase())) { - if (init) { - await exec_1.default('git', ['fetch', `--depth=${depth}`, 'origin', base, exports.HEAD]); - init = false; - } - else { + if (!(await hasMergeBase())) { + await exec_1.default('git', ['fetch', `--depth=${initialFetchDepth}`, 'origin', base, exports.HEAD]); + let depth = initialFetchDepth; + let lastCommitCount = await getCommitCount(); + while (!(await hasMergeBase())) { + depth = Math.min(depth * 2, Number.MAX_SAFE_INTEGER); await exec_1.default('git', ['fetch', `--deepen=${depth}`, 'origin', base, exports.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 exec_1.default('git', ['fetch']); - if (!(await hasMergeBase())) { - noMergeBase = true; + 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 exec_1.default('git', ['fetch']); + if (!(await hasMergeBase())) { + noMergeBase = true; + } + break; } - break; + lastCommitCount = commitCount; } - depth = Math.min(depth * 2, Number.MAX_SAFE_INTEGER); - lastCommitCount = commitCount; } } finally { diff --git a/src/git.ts b/src/git.ts index b31dedf2..d81b1f55 100644 --- a/src/git.ts +++ b/src/git.ts @@ -64,28 +64,25 @@ export async function getChangesSinceMergeBase(base: string, initialFetchDepth: let noMergeBase = false core.startGroup(`Searching for merge-base ${baseRef}...${HEAD}`) try { - let init = true - let lastCommitCount = await getCommitCount() - let depth = Math.max(lastCommitCount * 2, initialFetchDepth) - while (!(await hasMergeBase())) { - if (init) { - await exec('git', ['fetch', `--depth=${depth}`, 'origin', base, HEAD]) - init = false - } else { + if (!(await hasMergeBase())) { + await exec('git', ['fetch', `--depth=${initialFetchDepth}`, 'origin', base, HEAD]) + let depth = initialFetchDepth + let lastCommitCount = await getCommitCount() + while (!(await hasMergeBase())) { + depth = Math.min(depth * 2, Number.MAX_SAFE_INTEGER) await exec('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 exec('git', ['fetch']) - if (!(await hasMergeBase())) { - noMergeBase = true + 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 exec('git', ['fetch']) + if (!(await hasMergeBase())) { + noMergeBase = true + } + break } - break + lastCommitCount = commitCount } - depth = Math.min(depth * 2, Number.MAX_SAFE_INTEGER) - lastCommitCount = commitCount } } finally { core.endGroup() From 138368ff4f3d92d53cbfa56919e920c2d9711b60 Mon Sep 17 00:00:00 2001 From: Michal Dorner Date: Tue, 9 Mar 2021 21:56:18 +0100 Subject: [PATCH 3/4] Use ref instead of HEAD --- dist/index.js | 18 +++++++++--------- src/git.ts | 14 +++++++------- src/main.ts | 4 ++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/dist/index.js b/dist/index.js index 44274fb1..e79004f6 100644 --- a/dist/index.js +++ b/dist/index.js @@ -3865,21 +3865,21 @@ async function getChangesOnHead() { return parseGitDiffOutput(output); } exports.getChangesOnHead = getChangesOnHead; -async function getChangesSinceMergeBase(base, initialFetchDepth) { +async function getChangesSinceMergeBase(base, ref, initialFetchDepth) { const baseRef = `remotes/origin/${base}`; async function hasMergeBase() { - return (await exec_1.default('git', ['merge-base', baseRef, exports.HEAD], { ignoreReturnCode: true })).code === 0; + return (await exec_1.default('git', ['merge-base', baseRef, ref], { ignoreReturnCode: true })).code === 0; } let noMergeBase = false; - core.startGroup(`Searching for merge-base ${baseRef}...${exports.HEAD}`); + core.startGroup(`Searching for merge-base ${baseRef}...${ref}`); try { if (!(await hasMergeBase())) { - await exec_1.default('git', ['fetch', `--depth=${initialFetchDepth}`, 'origin', base, exports.HEAD]); + await exec_1.default('git', ['fetch', `--depth=${initialFetchDepth}`, 'origin', base, ref]); let depth = initialFetchDepth; let lastCommitCount = await getCommitCount(); while (!(await hasMergeBase())) { depth = Math.min(depth * 2, Number.MAX_SAFE_INTEGER); - await exec_1.default('git', ['fetch', `--deepen=${depth}`, 'origin', base, exports.HEAD]); + await exec_1.default('git', ['fetch', `--deepen=${depth}`, 'origin', base, ref]); const commitCount = await getCommitCount(); if (commitCount === lastCommitCount) { core.info('No more commits were fetched'); @@ -3902,11 +3902,11 @@ async function getChangesSinceMergeBase(base, initialFetchDepth) { return await listAllFilesAsAdded(); } // Get changes introduced on HEAD compared to ref - core.startGroup(`Change detection ${baseRef}...${exports.HEAD}`); + core.startGroup(`Change detection ${baseRef}...${ref}`); let output = ''; try { // Three dots '...' change detection - finds merge-base and compares against it - output = (await exec_1.default('git', ['diff', '--no-renames', '--name-status', '-z', `${baseRef}...${exports.HEAD}`])).stdout; + output = (await exec_1.default('git', ['diff', '--no-renames', '--name-status', '-z', `${baseRef}...${ref}`])).stdout; } finally { fixStdOutNullTermination(); @@ -4732,7 +4732,7 @@ async function getChangedFilesFromGit(base, initialFetchDepth) { if (baseSha === git.NULL_SHA) { if (defaultRef && baseRef !== defaultRef) { core.info(`First push of a branch detected - changes will be detected against the default branch ${defaultRef}`); - return await git.getChangesSinceMergeBase(defaultRef, initialFetchDepth); + return await git.getChangesSinceMergeBase(defaultRef, ref, initialFetchDepth); } else { core.info('Initial push detected - all files will be listed as added'); @@ -4744,7 +4744,7 @@ async function getChangedFilesFromGit(base, initialFetchDepth) { } // Changes introduced by current branch against the base branch core.info(`Changes will be detected against the branch ${baseRef}`); - return await git.getChangesSinceMergeBase(baseRef, initialFetchDepth); + return await git.getChangesSinceMergeBase(baseRef, ref, initialFetchDepth); } // Uses github REST api to get list of files changed in PR async function getChangedFilesFromApi(token, pullRequest) { diff --git a/src/git.ts b/src/git.ts index d81b1f55..531c301f 100644 --- a/src/git.ts +++ b/src/git.ts @@ -54,23 +54,23 @@ export async function getChangesOnHead(): Promise { return parseGitDiffOutput(output) } -export async function getChangesSinceMergeBase(base: string, initialFetchDepth: number): Promise { +export async function getChangesSinceMergeBase(base: string, ref: string, initialFetchDepth: number): Promise { const baseRef = `remotes/origin/${base}` async function hasMergeBase(): Promise { - return (await exec('git', ['merge-base', baseRef, HEAD], {ignoreReturnCode: true})).code === 0 + return (await exec('git', ['merge-base', baseRef, ref], {ignoreReturnCode: true})).code === 0 } let noMergeBase = false - core.startGroup(`Searching for merge-base ${baseRef}...${HEAD}`) + core.startGroup(`Searching for merge-base ${baseRef}...${ref}`) try { if (!(await hasMergeBase())) { - await exec('git', ['fetch', `--depth=${initialFetchDepth}`, 'origin', base, HEAD]) + await exec('git', ['fetch', `--depth=${initialFetchDepth}`, 'origin', base, ref]) let depth = initialFetchDepth let lastCommitCount = await getCommitCount() while (!(await hasMergeBase())) { depth = Math.min(depth * 2, Number.MAX_SAFE_INTEGER) - await exec('git', ['fetch', `--deepen=${depth}`, 'origin', base, HEAD]) + await exec('git', ['fetch', `--deepen=${depth}`, 'origin', base, ref]) const commitCount = await getCommitCount() if (commitCount === lastCommitCount) { core.info('No more commits were fetched') @@ -94,11 +94,11 @@ export async function getChangesSinceMergeBase(base: string, initialFetchDepth: } // Get changes introduced on HEAD compared to ref - core.startGroup(`Change detection ${baseRef}...${HEAD}`) + core.startGroup(`Change detection ${baseRef}...${ref}`) let output = '' try { // Three dots '...' change detection - finds merge-base and compares against it - output = (await exec('git', ['diff', '--no-renames', '--name-status', '-z', `${baseRef}...${HEAD}`])).stdout + output = (await exec('git', ['diff', '--no-renames', '--name-status', '-z', `${baseRef}...${ref}`])).stdout } finally { fixStdOutNullTermination() core.endGroup() diff --git a/src/main.ts b/src/main.ts index d9077963..e3d6ebc4 100644 --- a/src/main.ts +++ b/src/main.ts @@ -109,7 +109,7 @@ async function getChangedFilesFromGit(base: string, initialFetchDepth: number): if (baseSha === git.NULL_SHA) { if (defaultRef && baseRef !== defaultRef) { core.info(`First push of a branch detected - changes will be detected against the default branch ${defaultRef}`) - return await git.getChangesSinceMergeBase(defaultRef, initialFetchDepth) + return await git.getChangesSinceMergeBase(defaultRef, ref, initialFetchDepth) } else { core.info('Initial push detected - all files will be listed as added') return await git.listAllFilesAsAdded() @@ -122,7 +122,7 @@ async function getChangedFilesFromGit(base: string, initialFetchDepth: number): // Changes introduced by current branch against the base branch core.info(`Changes will be detected against the branch ${baseRef}`) - return await git.getChangesSinceMergeBase(baseRef, initialFetchDepth) + return await git.getChangesSinceMergeBase(baseRef, ref, initialFetchDepth) } // Uses github REST api to get list of files changed in PR From c64be944bffd61cd2f6280227b128670410483cf Mon Sep 17 00:00:00 2001 From: Michal Dorner Date: Tue, 9 Mar 2021 22:01:10 +0100 Subject: [PATCH 4/4] Update CHANGELOG --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a064e6b5..c1fac5fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## v2.9.2 +- [Fix fetching git history](https://github.com/dorny/paths-filter/pull/75) + ## v2.9.1 - [Fix fetching git history + fallback to unshallow repo](https://github.com/dorny/paths-filter/pull/74)