Skip to content

Commit cd7d8d6

Browse files
authored
Check git version before attempting to disable sparse-checkout (#1656)
* Check git version before attempting to disable `sparse-checkout` * Bump `MinimumGitSparseCheckoutVersion` to 2.28 due to #1386 * Initial prep for release 4.1.3
1 parent 8410ad0 commit cd7d8d6

8 files changed

+97
-30
lines changed

__test__/git-auth-helper.test.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,8 @@ async function setup(testName: string): Promise<void> {
796796
),
797797
tryDisableAutomaticGarbageCollection: jest.fn(),
798798
tryGetFetchUrl: jest.fn(),
799-
tryReset: jest.fn()
799+
tryReset: jest.fn(),
800+
version: jest.fn()
800801
}
801802

802803
settings = {

__test__/git-directory-helper.test.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ async function setup(testName: string): Promise<void> {
501501
}),
502502
tryReset: jest.fn(async () => {
503503
return true
504-
})
504+
}),
505+
version: jest.fn()
505506
}
506507
}

__test__/git-version.test.ts

+42-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import {GitVersion} from '../lib/git-version'
1+
import {GitVersion} from '../src/git-version'
2+
import {MinimumGitSparseCheckoutVersion} from '../src/git-command-manager'
23

34
describe('git-version tests', () => {
45
it('basics', async () => {
@@ -42,4 +43,44 @@ describe('git-version tests', () => {
4243
expect(version.checkMinimum(new GitVersion('5.1'))).toBeFalsy()
4344
expect(version.checkMinimum(new GitVersion('5.1.2'))).toBeFalsy()
4445
})
46+
47+
it('sparse checkout', async () => {
48+
const minSparseVer = MinimumGitSparseCheckoutVersion
49+
expect(new GitVersion('1.0').checkMinimum(minSparseVer)).toBeFalsy()
50+
expect(new GitVersion('1.99').checkMinimum(minSparseVer)).toBeFalsy()
51+
expect(new GitVersion('2.0').checkMinimum(minSparseVer)).toBeFalsy()
52+
expect(new GitVersion('2.24').checkMinimum(minSparseVer)).toBeFalsy()
53+
expect(new GitVersion('2.24.0').checkMinimum(minSparseVer)).toBeFalsy()
54+
expect(new GitVersion('2.24.9').checkMinimum(minSparseVer)).toBeFalsy()
55+
expect(new GitVersion('2.25').checkMinimum(minSparseVer)).toBeFalsy()
56+
expect(new GitVersion('2.25.0').checkMinimum(minSparseVer)).toBeFalsy()
57+
expect(new GitVersion('2.25.1').checkMinimum(minSparseVer)).toBeFalsy()
58+
expect(new GitVersion('2.25.9').checkMinimum(minSparseVer)).toBeFalsy()
59+
expect(new GitVersion('2.26').checkMinimum(minSparseVer)).toBeFalsy()
60+
expect(new GitVersion('2.26.0').checkMinimum(minSparseVer)).toBeFalsy()
61+
expect(new GitVersion('2.26.1').checkMinimum(minSparseVer)).toBeFalsy()
62+
expect(new GitVersion('2.26.9').checkMinimum(minSparseVer)).toBeFalsy()
63+
expect(new GitVersion('2.27').checkMinimum(minSparseVer)).toBeFalsy()
64+
expect(new GitVersion('2.27.0').checkMinimum(minSparseVer)).toBeFalsy()
65+
expect(new GitVersion('2.27.1').checkMinimum(minSparseVer)).toBeFalsy()
66+
expect(new GitVersion('2.27.9').checkMinimum(minSparseVer)).toBeFalsy()
67+
// /---------------------------------------
68+
// ^^^ before / after vvv
69+
// --------------------------/
70+
expect(new GitVersion('2.28').checkMinimum(minSparseVer)).toBeTruthy()
71+
expect(new GitVersion('2.28.0').checkMinimum(minSparseVer)).toBeTruthy()
72+
expect(new GitVersion('2.28.1').checkMinimum(minSparseVer)).toBeTruthy()
73+
expect(new GitVersion('2.28.9').checkMinimum(minSparseVer)).toBeTruthy()
74+
expect(new GitVersion('2.29').checkMinimum(minSparseVer)).toBeTruthy()
75+
expect(new GitVersion('2.29.0').checkMinimum(minSparseVer)).toBeTruthy()
76+
expect(new GitVersion('2.29.1').checkMinimum(minSparseVer)).toBeTruthy()
77+
expect(new GitVersion('2.29.9').checkMinimum(minSparseVer)).toBeTruthy()
78+
expect(new GitVersion('2.99').checkMinimum(minSparseVer)).toBeTruthy()
79+
expect(new GitVersion('3.0').checkMinimum(minSparseVer)).toBeTruthy()
80+
expect(new GitVersion('3.99').checkMinimum(minSparseVer)).toBeTruthy()
81+
expect(new GitVersion('4.0').checkMinimum(minSparseVer)).toBeTruthy()
82+
expect(new GitVersion('4.99').checkMinimum(minSparseVer)).toBeTruthy()
83+
expect(new GitVersion('5.0').checkMinimum(minSparseVer)).toBeTruthy()
84+
expect(new GitVersion('5.99').checkMinimum(minSparseVer)).toBeTruthy()
85+
})
4586
})

dist/index.js

+23-12
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
467467
});
468468
};
469469
Object.defineProperty(exports, "__esModule", ({ value: true }));
470-
exports.createCommandManager = exports.MinimumGitVersion = void 0;
470+
exports.createCommandManager = exports.MinimumGitSparseCheckoutVersion = exports.MinimumGitVersion = void 0;
471471
const core = __importStar(__nccwpck_require__(2186));
472472
const exec = __importStar(__nccwpck_require__(1514));
473473
const fs = __importStar(__nccwpck_require__(7147));
@@ -480,7 +480,9 @@ const retryHelper = __importStar(__nccwpck_require__(2155));
480480
const git_version_1 = __nccwpck_require__(3142);
481481
// Auth header not supported before 2.9
482482
// Wire protocol v2 not supported before 2.18
483+
// sparse-checkout not [well-]supported before 2.28 (see https://github.com/actions/checkout/issues/1386)
483484
exports.MinimumGitVersion = new git_version_1.GitVersion('2.18');
485+
exports.MinimumGitSparseCheckoutVersion = new git_version_1.GitVersion('2.28');
484486
function createCommandManager(workingDirectory, lfs, doSparseCheckout) {
485487
return __awaiter(this, void 0, void 0, function* () {
486488
return yield GitCommandManager.createCommandManager(workingDirectory, lfs, doSparseCheckout);
@@ -498,6 +500,7 @@ class GitCommandManager {
498500
this.lfs = false;
499501
this.doSparseCheckout = false;
500502
this.workingDirectory = '';
503+
this.gitVersion = new git_version_1.GitVersion();
501504
}
502505
branchDelete(remote, branch) {
503506
return __awaiter(this, void 0, void 0, function* () {
@@ -850,6 +853,11 @@ class GitCommandManager {
850853
return output.exitCode === 0;
851854
});
852855
}
856+
version() {
857+
return __awaiter(this, void 0, void 0, function* () {
858+
return this.gitVersion;
859+
});
860+
}
853861
static createCommandManager(workingDirectory, lfs, doSparseCheckout) {
854862
return __awaiter(this, void 0, void 0, function* () {
855863
const result = new GitCommandManager();
@@ -901,21 +909,21 @@ class GitCommandManager {
901909
this.gitPath = yield io.which('git', true);
902910
// Git version
903911
core.debug('Getting git version');
904-
let gitVersion = new git_version_1.GitVersion();
912+
this.gitVersion = new git_version_1.GitVersion();
905913
let gitOutput = yield this.execGit(['version']);
906914
let stdout = gitOutput.stdout.trim();
907915
if (!stdout.includes('\n')) {
908916
const match = stdout.match(/\d+\.\d+(\.\d+)?/);
909917
if (match) {
910-
gitVersion = new git_version_1.GitVersion(match[0]);
918+
this.gitVersion = new git_version_1.GitVersion(match[0]);
911919
}
912920
}
913-
if (!gitVersion.isValid()) {
921+
if (!this.gitVersion.isValid()) {
914922
throw new Error('Unable to determine git version');
915923
}
916924
// Minimum git version
917-
if (!gitVersion.checkMinimum(exports.MinimumGitVersion)) {
918-
throw new Error(`Minimum required git version is ${exports.MinimumGitVersion}. Your git ('${this.gitPath}') is ${gitVersion}`);
925+
if (!this.gitVersion.checkMinimum(exports.MinimumGitVersion)) {
926+
throw new Error(`Minimum required git version is ${exports.MinimumGitVersion}. Your git ('${this.gitPath}') is ${this.gitVersion}`);
919927
}
920928
if (this.lfs) {
921929
// Git-lfs version
@@ -943,14 +951,12 @@ class GitCommandManager {
943951
}
944952
this.doSparseCheckout = doSparseCheckout;
945953
if (this.doSparseCheckout) {
946-
// The `git sparse-checkout` command was introduced in Git v2.25.0
947-
const minimumGitSparseCheckoutVersion = new git_version_1.GitVersion('2.25');
948-
if (!gitVersion.checkMinimum(minimumGitSparseCheckoutVersion)) {
949-
throw new Error(`Minimum Git version required for sparse checkout is ${minimumGitSparseCheckoutVersion}. Your git ('${this.gitPath}') is ${gitVersion}`);
954+
if (!this.gitVersion.checkMinimum(exports.MinimumGitSparseCheckoutVersion)) {
955+
throw new Error(`Minimum Git version required for sparse checkout is ${exports.MinimumGitSparseCheckoutVersion}. Your git ('${this.gitPath}') is ${this.gitVersion}`);
950956
}
951957
}
952958
// Set the user agent
953-
const gitHttpUserAgent = `git/${gitVersion} (github-actions-checkout)`;
959+
const gitHttpUserAgent = `git/${this.gitVersion} (github-actions-checkout)`;
954960
core.debug(`Set git useragent to: ${gitHttpUserAgent}`);
955961
this.gitEnv['GIT_HTTP_USER_AGENT'] = gitHttpUserAgent;
956962
});
@@ -1155,6 +1161,7 @@ const path = __importStar(__nccwpck_require__(1017));
11551161
const refHelper = __importStar(__nccwpck_require__(8601));
11561162
const stateHelper = __importStar(__nccwpck_require__(8647));
11571163
const urlHelper = __importStar(__nccwpck_require__(9437));
1164+
const git_command_manager_1 = __nccwpck_require__(738);
11581165
function getSource(settings) {
11591166
return __awaiter(this, void 0, void 0, function* () {
11601167
// Repository URL
@@ -1288,7 +1295,11 @@ function getSource(settings) {
12881295
}
12891296
// Sparse checkout
12901297
if (!settings.sparseCheckout) {
1291-
yield git.disableSparseCheckout();
1298+
let gitVersion = yield git.version();
1299+
// no need to disable sparse-checkout if the installed git runtime doesn't even support it.
1300+
if (gitVersion.checkMinimum(git_command_manager_1.MinimumGitSparseCheckoutVersion)) {
1301+
yield git.disableSparseCheckout();
1302+
}
12921303
}
12931304
else {
12941305
core.startGroup('Setting up sparse checkout');

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "checkout",
3-
"version": "4.1.2",
3+
"version": "4.1.3",
44
"description": "checkout action",
55
"main": "lib/main.js",
66
"scripts": {

src/git-command-manager.ts

+16-10
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import {GitVersion} from './git-version'
1111

1212
// Auth header not supported before 2.9
1313
// Wire protocol v2 not supported before 2.18
14+
// sparse-checkout not [well-]supported before 2.28 (see https://github.com/actions/checkout/issues/1386)
1415
export const MinimumGitVersion = new GitVersion('2.18')
16+
export const MinimumGitSparseCheckoutVersion = new GitVersion('2.28')
1517

1618
export interface IGitCommandManager {
1719
branchDelete(remote: boolean, branch: string): Promise<void>
@@ -60,6 +62,7 @@ export interface IGitCommandManager {
6062
tryDisableAutomaticGarbageCollection(): Promise<boolean>
6163
tryGetFetchUrl(): Promise<string>
6264
tryReset(): Promise<boolean>
65+
version(): Promise<GitVersion>
6366
}
6467

6568
export async function createCommandManager(
@@ -83,6 +86,7 @@ class GitCommandManager {
8386
private lfs = false
8487
private doSparseCheckout = false
8588
private workingDirectory = ''
89+
private gitVersion: GitVersion = new GitVersion()
8690

8791
// Private constructor; use createCommandManager()
8892
private constructor() {}
@@ -480,6 +484,10 @@ class GitCommandManager {
480484
return output.exitCode === 0
481485
}
482486

487+
async version(): Promise<GitVersion> {
488+
return this.gitVersion
489+
}
490+
483491
static async createCommandManager(
484492
workingDirectory: string,
485493
lfs: boolean,
@@ -556,23 +564,23 @@ class GitCommandManager {
556564

557565
// Git version
558566
core.debug('Getting git version')
559-
let gitVersion = new GitVersion()
567+
this.gitVersion = new GitVersion()
560568
let gitOutput = await this.execGit(['version'])
561569
let stdout = gitOutput.stdout.trim()
562570
if (!stdout.includes('\n')) {
563571
const match = stdout.match(/\d+\.\d+(\.\d+)?/)
564572
if (match) {
565-
gitVersion = new GitVersion(match[0])
573+
this.gitVersion = new GitVersion(match[0])
566574
}
567575
}
568-
if (!gitVersion.isValid()) {
576+
if (!this.gitVersion.isValid()) {
569577
throw new Error('Unable to determine git version')
570578
}
571579

572580
// Minimum git version
573-
if (!gitVersion.checkMinimum(MinimumGitVersion)) {
581+
if (!this.gitVersion.checkMinimum(MinimumGitVersion)) {
574582
throw new Error(
575-
`Minimum required git version is ${MinimumGitVersion}. Your git ('${this.gitPath}') is ${gitVersion}`
583+
`Minimum required git version is ${MinimumGitVersion}. Your git ('${this.gitPath}') is ${this.gitVersion}`
576584
)
577585
}
578586

@@ -606,16 +614,14 @@ class GitCommandManager {
606614

607615
this.doSparseCheckout = doSparseCheckout
608616
if (this.doSparseCheckout) {
609-
// The `git sparse-checkout` command was introduced in Git v2.25.0
610-
const minimumGitSparseCheckoutVersion = new GitVersion('2.25')
611-
if (!gitVersion.checkMinimum(minimumGitSparseCheckoutVersion)) {
617+
if (!this.gitVersion.checkMinimum(MinimumGitSparseCheckoutVersion)) {
612618
throw new Error(
613-
`Minimum Git version required for sparse checkout is ${minimumGitSparseCheckoutVersion}. Your git ('${this.gitPath}') is ${gitVersion}`
619+
`Minimum Git version required for sparse checkout is ${MinimumGitSparseCheckoutVersion}. Your git ('${this.gitPath}') is ${this.gitVersion}`
614620
)
615621
}
616622
}
617623
// Set the user agent
618-
const gitHttpUserAgent = `git/${gitVersion} (github-actions-checkout)`
624+
const gitHttpUserAgent = `git/${this.gitVersion} (github-actions-checkout)`
619625
core.debug(`Set git useragent to: ${gitHttpUserAgent}`)
620626
this.gitEnv['GIT_HTTP_USER_AGENT'] = gitHttpUserAgent
621627
}

src/git-source-provider.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import * as path from 'path'
99
import * as refHelper from './ref-helper'
1010
import * as stateHelper from './state-helper'
1111
import * as urlHelper from './url-helper'
12-
import {IGitCommandManager} from './git-command-manager'
12+
import {
13+
MinimumGitSparseCheckoutVersion,
14+
IGitCommandManager
15+
} from './git-command-manager'
1316
import {IGitSourceSettings} from './git-source-settings'
1417

1518
export async function getSource(settings: IGitSourceSettings): Promise<void> {
@@ -209,7 +212,11 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
209212

210213
// Sparse checkout
211214
if (!settings.sparseCheckout) {
212-
await git.disableSparseCheckout()
215+
let gitVersion = await git.version()
216+
// no need to disable sparse-checkout if the installed git runtime doesn't even support it.
217+
if (gitVersion.checkMinimum(MinimumGitSparseCheckoutVersion)) {
218+
await git.disableSparseCheckout()
219+
}
213220
} else {
214221
core.startGroup('Setting up sparse checkout')
215222
if (settings.sparseCheckoutConeMode) {

0 commit comments

Comments
 (0)