diff --git a/README.md b/README.md index 5509e7d1..59acda12 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,8 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/ # Default: true clean: '' - # Partially clone against a given filter. Overrides sparse-checkout if set. + # Partially clone against a given filter. If sparse-checkout is set and filter is + # not, the filter is `blob:none`. Set to `none` to fetch without a filter. # Default: null filter: '' diff --git a/__test__/git-command-manager.test.ts b/__test__/git-command-manager.test.ts index e669c0f3..f03b587e 100644 --- a/__test__/git-command-manager.test.ts +++ b/__test__/git-command-manager.test.ts @@ -401,6 +401,41 @@ describe('Test fetchDepth and fetchTags options', () => { expect.any(Object) ) }) + + it('should not pass --filter when filter is not set', async () => { + // exec.exec is already mockExec + const workingDirectory = 'test' + const lfs = false + const doSparseCheckout = false + git = await commandManager.createCommandManager( + workingDirectory, + lfs, + doSparseCheckout + ) + + const refSpec = ['refspec1'] + const options = { + fetchDepth: 1 + } + + await git.fetch(refSpec, options) + + expect(mockExec).toHaveBeenCalledWith( + expect.any(String), + [ + '-c', + 'protocol.version=2', + 'fetch', + '--no-tags', + '--prune', + '--no-recurse-submodules', + '--depth=1', + 'origin', + 'refspec1' + ], + expect.any(Object) + ) + }) }) describe('repository initialization object format', () => { diff --git a/__test__/input-helper.test.ts b/__test__/input-helper.test.ts index afe30fb8..323c9ed9 100644 --- a/__test__/input-helper.test.ts +++ b/__test__/input-helper.test.ts @@ -215,6 +215,47 @@ describe('input-helper tests', () => { expect(settings.commit).toBe('1111111111222222222233333333334444444444') }) + describe('filter', () => { + it('is not set without sparse checkout', async () => { + const settings: IGitSourceSettings = await inputHelper.getInputs() + expect(settings.filter).toBe(undefined) + }) + + it('defaults to blob:none with sparse checkout', async () => { + inputs['sparse-checkout'] = 'src\ndocs' + const settings: IGitSourceSettings = await inputHelper.getInputs() + expect(settings.sparseCheckout).toEqual(['src', 'docs']) + expect(settings.filter).toBe('blob:none') + }) + + it('uses the given filter with sparse checkout', async () => { + inputs['sparse-checkout'] = 'src' + inputs.filter = 'tree:0' + const settings: IGitSourceSettings = await inputHelper.getInputs() + expect(settings.filter).toBe('tree:0') + }) + + it('uses the given filter without sparse checkout', async () => { + inputs.filter = 'blob:limit=1m' + const settings: IGitSourceSettings = await inputHelper.getInputs() + expect(settings.filter).toBe('blob:limit=1m') + }) + + it('is not set when none with sparse checkout', async () => { + inputs['sparse-checkout'] = 'src' + inputs.filter = 'none' + const settings: IGitSourceSettings = await inputHelper.getInputs() + expect(settings.sparseCheckout).toEqual(['src']) + expect(settings.filter).toBe(undefined) + }) + + it('is not set when none without sparse checkout', async () => { + inputs.filter = 'None' + const settings: IGitSourceSettings = await inputHelper.getInputs() + expect(settings.filter).toBe(undefined) + }) + }) + it('sets workflow organization ID', async () => { const settings: IGitSourceSettings = await inputHelper.getInputs() expect(settings.workflowOrganizationId).toBe(123456) diff --git a/action.yml b/action.yml index 5b0524f7..78875c36 100644 --- a/action.yml +++ b/action.yml @@ -60,7 +60,8 @@ inputs: filter: description: > Partially clone against a given filter. - Overrides sparse-checkout if set. + If sparse-checkout is set and filter is not, the filter is `blob:none`. + Set to `none` to fetch without a filter. default: null sparse-checkout: description: > diff --git a/dist/index.js b/dist/index.js index 06ae5d22..8caa5751 100644 --- a/dist/index.js +++ b/dist/index.js @@ -41810,9 +41810,6 @@ async function getSource(settings) { if (settings.filter) { fetchOptions.filter = settings.filter; } - else if (settings.sparseCheckout) { - fetchOptions.filter = 'blob:none'; - } if (settings.fetchDepth <= 0) { // Fetch all branches and tags let refSpec = getRefSpecForAllHistory(settings.ref, settings.commit); @@ -42137,18 +42134,26 @@ async function getInputs() { // Clean result.clean = (getInput('clean') || 'true').toUpperCase() === 'TRUE'; core_debug(`clean = ${result.clean}`); - // Filter - const filter = getInput('filter'); - if (filter) { - result.filter = filter; - } - core_debug(`filter = ${result.filter}`); // Sparse checkout const sparseCheckout = getMultilineInput('sparse-checkout'); if (sparseCheckout.length) { result.sparseCheckout = sparseCheckout; core_debug(`sparse checkout = ${result.sparseCheckout}`); } + // Filter + // Sparse checkout implies 'blob:none' unless a filter is given. + // 'none' disables the filter. + const filter = getInput('filter'); + if (filter.toUpperCase() === 'NONE') { + result.filter = undefined; + } + else if (filter) { + result.filter = filter; + } + else if (result.sparseCheckout) { + result.filter = 'blob:none'; + } + core_debug(`filter = ${result.filter}`); result.sparseCheckoutConeMode = (getInput('sparse-checkout-cone-mode') || 'true').toUpperCase() === 'TRUE'; diff --git a/src/git-source-provider.ts b/src/git-source-provider.ts index b9c1d357..dad5d358 100644 --- a/src/git-source-provider.ts +++ b/src/git-source-provider.ts @@ -181,8 +181,6 @@ export async function getSource(settings: IGitSourceSettings): Promise { if (settings.filter) { fetchOptions.filter = settings.filter - } else if (settings.sparseCheckout) { - fetchOptions.filter = 'blob:none' } if (settings.fetchDepth <= 0) { diff --git a/src/git-source-settings.ts b/src/git-source-settings.ts index 79041c43..eab36688 100644 --- a/src/git-source-settings.ts +++ b/src/git-source-settings.ts @@ -30,7 +30,8 @@ export interface IGitSourceSettings { clean: boolean /** - * The filter determining which objects to include + * The filter determining which objects to include. + * Defaults to 'blob:none' when sparse checkout is set, unless the input is 'none'. */ filter: string | undefined diff --git a/src/input-helper.ts b/src/input-helper.ts index 9a98b867..b57150de 100644 --- a/src/input-helper.ts +++ b/src/input-helper.ts @@ -100,14 +100,6 @@ export async function getInputs(): Promise { result.clean = (core.getInput('clean') || 'true').toUpperCase() === 'TRUE' core.debug(`clean = ${result.clean}`) - // Filter - const filter = core.getInput('filter') - if (filter) { - result.filter = filter - } - - core.debug(`filter = ${result.filter}`) - // Sparse checkout const sparseCheckout = core.getMultilineInput('sparse-checkout') if (sparseCheckout.length) { @@ -115,6 +107,20 @@ export async function getInputs(): Promise { core.debug(`sparse checkout = ${result.sparseCheckout}`) } + // Filter + // Sparse checkout implies 'blob:none' unless a filter is given. + // 'none' disables the filter. + const filter = core.getInput('filter') + if (filter.toUpperCase() === 'NONE') { + result.filter = undefined + } else if (filter) { + result.filter = filter + } else if (result.sparseCheckout) { + result.filter = 'blob:none' + } + + core.debug(`filter = ${result.filter}`) + result.sparseCheckoutConeMode = (core.getInput('sparse-checkout-cone-mode') || 'true').toUpperCase() === 'TRUE'