Skip to content

Commit

Permalink
sparse-checkout: optionally turn off cone mode
Browse files Browse the repository at this point in the history
While it _is_ true that cone mode is the default nowadays (mainly for
performance reasons: code mode is much faster than non-cone mode), there
_are_ legitimate use cases where non-cone mode is really useful.

Let's add a flag to optionally disable cone mode.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
  • Loading branch information
dscho committed Jun 3, 2023
1 parent 9f59c81 commit 0d9db6b
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 2 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/test.yml
Expand Up @@ -85,6 +85,20 @@ jobs:
- name: Verify sparse checkout
run: __test__/verify-sparse-checkout.sh

# Sparse checkout (non-cone mode)
- name: Sparse checkout (non-cone mode)
uses: ./
with:
sparse-checkout: |
/__test__/
/.github/
/dist/
sparse-checkout-cone-mode: false
path: sparse-checkout-non-cone-mode

- name: Verify sparse checkout (non-cone mode)
run: __test__/verify-sparse-checkout-non-cone-mode.sh

# LFS
- name: Checkout LFS
uses: ./
Expand Down
15 changes: 15 additions & 0 deletions README.md
Expand Up @@ -79,6 +79,10 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
# Default: null
sparse-checkout: ''

# Specifies whether to use cone-mode when doing a sparse checkout.
# Default: true
sparse-checkout-cone-mode: ''

# Number of commits to fetch. 0 indicates all history for all branches and tags.
# Default: 1
fetch-depth: ''
Expand Down Expand Up @@ -113,6 +117,7 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl

- [Fetch only the root files](#Fetch-only-the-root-files)
- [Fetch only the root files and `.github` and `src` folder](#Fetch-only-the-root-files-and-github-and-src-folder)
- [Fetch only a single file](#Fetch-only-a-single-file)
- [Fetch all history for all tags and branches](#Fetch-all-history-for-all-tags-and-branches)
- [Checkout a different branch](#Checkout-a-different-branch)
- [Checkout HEAD^](#Checkout-HEAD)
Expand Down Expand Up @@ -141,6 +146,16 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
src
```

## Fetch only a single file

```yaml
- uses: actions/checkout@v3
with:
sparse-checkout: |
README.md
sparse-checkout-cone-mode: false
```

## Fetch all history for all tags and branches

```yaml
Expand Down
2 changes: 2 additions & 0 deletions __test__/git-auth-helper.test.ts
Expand Up @@ -728,6 +728,7 @@ async function setup(testName: string): Promise<void> {
branchExists: jest.fn(),
branchList: jest.fn(),
sparseCheckout: jest.fn(),
sparseCheckoutNonConeMode: jest.fn(),
checkout: jest.fn(),
checkoutDetach: jest.fn(),
config: jest.fn(
Expand Down Expand Up @@ -802,6 +803,7 @@ async function setup(testName: string): Promise<void> {
clean: true,
commit: '',
sparseCheckout: [],
sparseCheckoutConeMode: true,
fetchDepth: 1,
lfs: false,
submodules: false,
Expand Down
1 change: 1 addition & 0 deletions __test__/git-directory-helper.test.ts
Expand Up @@ -463,6 +463,7 @@ async function setup(testName: string): Promise<void> {
return []
}),
sparseCheckout: jest.fn(),
sparseCheckoutNonConeMode: jest.fn(),
checkout: jest.fn(),
checkoutDetach: jest.fn(),
config: jest.fn(),
Expand Down
1 change: 1 addition & 0 deletions __test__/input-helper.test.ts
Expand Up @@ -80,6 +80,7 @@ describe('input-helper tests', () => {
expect(settings.commit).toBeTruthy()
expect(settings.commit).toBe('1234567890123456789012345678901234567890')
expect(settings.sparseCheckout).toBe(undefined)
expect(settings.sparseCheckoutConeMode).toBe(true)
expect(settings.fetchDepth).toBe(1)
expect(settings.lfs).toBe(false)
expect(settings.ref).toBe('refs/heads/some-ref')
Expand Down
51 changes: 51 additions & 0 deletions __test__/verify-sparse-checkout-non-cone-mode.sh
@@ -0,0 +1,51 @@
#!/bin/sh

# Verify .git folder
if [ ! -d "./sparse-checkout-non-cone-mode/.git" ]; then
echo "Expected ./sparse-checkout-non-cone-mode/.git folder to exist"
exit 1
fi

# Verify sparse-checkout (non-cone-mode)
cd sparse-checkout-non-cone-mode

ENABLED=$(git config --local --get-all core.sparseCheckout)

if [ "$?" != "0" ]; then
echo "Failed to verify that sparse-checkout is enabled"
exit 1
fi

# Check that sparse-checkout is enabled
if [ "$ENABLED" != "true" ]; then
echo "Expected sparse-checkout to be enabled (is: $ENABLED)"
exit 1
fi

SPARSE_CHECKOUT_FILE=$(git rev-parse --git-path info/sparse-checkout)

if [ "$?" != "0" ]; then
echo "Failed to validate sparse-checkout"
exit 1
fi

# Check that sparse-checkout list is not empty
if [ ! -f "$SPARSE_CHECKOUT_FILE" ]; then
echo "Expected sparse-checkout file to exist"
exit 1
fi

# Check that all folders from sparse-checkout exists
for pattern in $(cat "$SPARSE_CHECKOUT_FILE")
do
if [ ! -d "$pattern" ]; then
echo "Expected directory '$pattern' to exist"
exit 1
fi
done

# Verify that the root directory is not checked out
if [ -f README.md ]; then
echo "Expected top-level files not to exist"
exit 1
fi
4 changes: 4 additions & 0 deletions action.yml
Expand Up @@ -58,6 +58,10 @@ inputs:
Do a sparse checkout on given patterns.
Each pattern should be separated with new lines
default: null
sparse-checkout-cone-mode:
description: >
Specifies whether to use cone-mode when doing a sparse checkout.
default: true
fetch-depth:
description: 'Number of commits to fetch. 0 indicates all history for all branches and tags.'
default: 1
Expand Down
23 changes: 22 additions & 1 deletion dist/index.js
Expand Up @@ -470,6 +470,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.createCommandManager = exports.MinimumGitVersion = void 0;
const core = __importStar(__nccwpck_require__(2186));
const exec = __importStar(__nccwpck_require__(1514));
const fs = __importStar(__nccwpck_require__(7147));
const fshelper = __importStar(__nccwpck_require__(7219));
const io = __importStar(__nccwpck_require__(7436));
const path = __importStar(__nccwpck_require__(1017));
Expand Down Expand Up @@ -579,6 +580,18 @@ class GitCommandManager {
yield this.execGit(['sparse-checkout', 'set', ...sparseCheckout]);
});
}
sparseCheckoutNonConeMode(sparseCheckout) {
return __awaiter(this, void 0, void 0, function* () {
yield this.execGit(['config', 'core.sparseCheckout', 'true']);
const output = yield this.execGit([
'rev-parse',
'--git-path',
'info/sparse-checkout'
]);
const sparseCheckoutPath = output.stdout.trimRight();
yield fs.promises.appendFile(sparseCheckoutPath, `\n${sparseCheckout.join('\n')}\n`);
});
}
checkout(ref, startPoint) {
return __awaiter(this, void 0, void 0, function* () {
const args = ['checkout', '--progress', '--force'];
Expand Down Expand Up @@ -1253,7 +1266,12 @@ function getSource(settings) {
// Sparse checkout
if (settings.sparseCheckout) {
core.startGroup('Setting up sparse checkout');
yield git.sparseCheckout(settings.sparseCheckout);
if (settings.sparseCheckoutConeMode) {
yield git.sparseCheckout(settings.sparseCheckout);
}
else {
yield git.sparseCheckoutNonConeMode(settings.sparseCheckout);
}
core.endGroup();
}
// Checkout
Expand Down Expand Up @@ -1697,6 +1715,9 @@ function getInputs() {
result.sparseCheckout = sparseCheckout;
core.debug(`sparse checkout = ${result.sparseCheckout}`);
}
result.sparseCheckoutConeMode =
(core.getInput('sparse-checkout-cone-mode') || 'true').toUpperCase() !==
'FALSE';
// Fetch depth
result.fetchDepth = Math.floor(Number(core.getInput('fetch-depth') || '1'));
if (isNaN(result.fetchDepth) || result.fetchDepth < 0) {
Expand Down
16 changes: 16 additions & 0 deletions src/git-command-manager.ts
@@ -1,5 +1,6 @@
import * as core from '@actions/core'
import * as exec from '@actions/exec'
import * as fs from 'fs'
import * as fshelper from './fs-helper'
import * as io from '@actions/io'
import * as path from 'path'
Expand All @@ -17,6 +18,7 @@ export interface IGitCommandManager {
branchExists(remote: boolean, pattern: string): Promise<boolean>
branchList(remote: boolean): Promise<string[]>
sparseCheckout(sparseCheckout: string[]): Promise<void>
sparseCheckoutNonConeMode(sparseCheckout: string[]): Promise<void>
checkout(ref: string, startPoint: string): Promise<void>
checkoutDetach(): Promise<void>
config(
Expand Down Expand Up @@ -165,6 +167,20 @@ class GitCommandManager {
await this.execGit(['sparse-checkout', 'set', ...sparseCheckout])
}

async sparseCheckoutNonConeMode(sparseCheckout: string[]): Promise<void> {
await this.execGit(['config', 'core.sparseCheckout', 'true'])
const output = await this.execGit([
'rev-parse',
'--git-path',
'info/sparse-checkout'
])
const sparseCheckoutPath = output.stdout.trimRight()
await fs.promises.appendFile(
sparseCheckoutPath,
`\n${sparseCheckout.join('\n')}\n`
)
}

async checkout(ref: string, startPoint: string): Promise<void> {
const args = ['checkout', '--progress', '--force']
if (startPoint) {
Expand Down
6 changes: 5 additions & 1 deletion src/git-source-provider.ts
Expand Up @@ -197,7 +197,11 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
// Sparse checkout
if (settings.sparseCheckout) {
core.startGroup('Setting up sparse checkout')
await git.sparseCheckout(settings.sparseCheckout)
if (settings.sparseCheckoutConeMode) {
await git.sparseCheckout(settings.sparseCheckout)
} else {
await git.sparseCheckoutNonConeMode(settings.sparseCheckout)
}
core.endGroup()
}

Expand Down
5 changes: 5 additions & 0 deletions src/git-source-settings.ts
Expand Up @@ -34,6 +34,11 @@ export interface IGitSourceSettings {
*/
sparseCheckout: string[]

/**
* Indicates whether to use cone mode in the sparse checkout (if any)
*/
sparseCheckoutConeMode: boolean

/**
* The depth when fetching
*/
Expand Down
4 changes: 4 additions & 0 deletions src/input-helper.ts
Expand Up @@ -89,6 +89,10 @@ export async function getInputs(): Promise<IGitSourceSettings> {
core.debug(`sparse checkout = ${result.sparseCheckout}`)
}

result.sparseCheckoutConeMode =
(core.getInput('sparse-checkout-cone-mode') || 'true').toUpperCase() !==
'FALSE'

// Fetch depth
result.fetchDepth = Math.floor(Number(core.getInput('fetch-depth') || '1'))
if (isNaN(result.fetchDepth) || result.fetchDepth < 0) {
Expand Down

0 comments on commit 0d9db6b

Please sign in to comment.