From c4602b42ee2a5f835f91eb29a5f4e55c060afa82 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 7 Jun 2023 08:57:04 +0200 Subject: [PATCH] Verify minimum Git version for sparse checkout The `git sparse-checkout` command is available only since Git version v2.25.0. The `actions/checkout` Action actually supports older Git versions than that; As of time of writing, the minimum version is v2.18.0. Instead of raising this minimum version even for users who do not require a sparse checkout, only check for this minimum version specifically when a sparse checkout was asked for. Suggested-by: Tingluo Huang Signed-off-by: Johannes Schindelin --- __test__/git-command-manager.test.ts | 6 ++++-- dist/index.js | 23 ++++++++++++++++------- src/git-command-manager.ts | 28 +++++++++++++++++++++++----- src/git-source-provider.ts | 5 +++-- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/__test__/git-command-manager.test.ts b/__test__/git-command-manager.test.ts index 6944ff743..808362398 100644 --- a/__test__/git-command-manager.test.ts +++ b/__test__/git-command-manager.test.ts @@ -39,7 +39,8 @@ describe('git-auth-helper tests', () => { jest.spyOn(exec, 'exec').mockImplementation(mockExec) const workingDirectory = 'test' const lfs = false - git = await commandManager.createCommandManager(workingDirectory, lfs) + const doSparseCheckout = false + git = await commandManager.createCommandManager(workingDirectory, lfs, doSparseCheckout) let branches = await git.branchList(false) @@ -70,7 +71,8 @@ describe('git-auth-helper tests', () => { jest.spyOn(exec, 'exec').mockImplementation(mockExec) const workingDirectory = 'test' const lfs = false - git = await commandManager.createCommandManager(workingDirectory, lfs) + const doSparseCheckout = false + git = await commandManager.createCommandManager(workingDirectory, lfs, doSparseCheckout) let branches = await git.branchList(false) diff --git a/dist/index.js b/dist/index.js index ca47b4af8..41d9585f4 100644 --- a/dist/index.js +++ b/dist/index.js @@ -481,9 +481,9 @@ const git_version_1 = __nccwpck_require__(3142); // Auth header not supported before 2.9 // Wire protocol v2 not supported before 2.18 exports.MinimumGitVersion = new git_version_1.GitVersion('2.18'); -function createCommandManager(workingDirectory, lfs) { +function createCommandManager(workingDirectory, lfs, doSparseCheckout) { return __awaiter(this, void 0, void 0, function* () { - return yield GitCommandManager.createCommandManager(workingDirectory, lfs); + return yield GitCommandManager.createCommandManager(workingDirectory, lfs, doSparseCheckout); }); } exports.createCommandManager = createCommandManager; @@ -496,6 +496,7 @@ class GitCommandManager { }; this.gitPath = ''; this.lfs = false; + this.doSparseCheckout = false; this.workingDirectory = ''; } branchDelete(remote, branch) { @@ -841,10 +842,10 @@ class GitCommandManager { return output.exitCode === 0; }); } - static createCommandManager(workingDirectory, lfs) { + static createCommandManager(workingDirectory, lfs, sparseCheckout) { return __awaiter(this, void 0, void 0, function* () { const result = new GitCommandManager(); - yield result.initializeCommandManager(workingDirectory, lfs); + yield result.initializeCommandManager(workingDirectory, lfs, sparseCheckout); return result; }); } @@ -880,7 +881,7 @@ class GitCommandManager { return result; }); } - initializeCommandManager(workingDirectory, lfs) { + initializeCommandManager(workingDirectory, lfs, sparseCheckout) { return __awaiter(this, void 0, void 0, function* () { this.workingDirectory = workingDirectory; // Git-lfs will try to pull down assets if any of the local/user/system setting exist. @@ -932,6 +933,14 @@ class GitCommandManager { throw new Error(`Minimum required git-lfs version is ${minimumGitLfsVersion}. Your git-lfs ('${gitLfsPath}') is ${gitLfsVersion}`); } } + this.doSparseCheckout = sparseCheckout; + if (this.doSparseCheckout) { + // The `git sparse-checkout` command was introduced in Git v2.25.0 + const minimumGitSparseCheckoutVersion = new git_version_1.GitVersion('2.25'); + if (!gitVersion.checkMinimum(minimumGitSparseCheckoutVersion)) { + throw new Error(`Minimum Git version required for sparse checkout is ${minimumGitSparseCheckoutVersion}. Your git ('${this.gitPath}') is ${gitVersion}`); + } + } // Set the user agent const gitHttpUserAgent = `git/${gitVersion} (github-actions-checkout)`; core.debug(`Set git useragent to: ${gitHttpUserAgent}`); @@ -1327,7 +1336,7 @@ function cleanup(repositoryPath) { } let git; try { - git = yield gitCommandManager.createCommandManager(repositoryPath, false); + git = yield gitCommandManager.createCommandManager(repositoryPath, false, false); } catch (_a) { return; @@ -1358,7 +1367,7 @@ function getGitCommandManager(settings) { return __awaiter(this, void 0, void 0, function* () { core.info(`Working directory is '${settings.repositoryPath}'`); try { - return yield gitCommandManager.createCommandManager(settings.repositoryPath, settings.lfs); + return yield gitCommandManager.createCommandManager(settings.repositoryPath, settings.lfs, settings.sparseCheckout != null); } catch (err) { // Git is required for LFS diff --git a/src/git-command-manager.ts b/src/git-command-manager.ts index 9ef94884e..4f6dc795d 100644 --- a/src/git-command-manager.ts +++ b/src/git-command-manager.ts @@ -61,9 +61,14 @@ export interface IGitCommandManager { export async function createCommandManager( workingDirectory: string, - lfs: boolean + lfs: boolean, + doSparseCheckout: boolean ): Promise { - return await GitCommandManager.createCommandManager(workingDirectory, lfs) + return await GitCommandManager.createCommandManager( + workingDirectory, + lfs, + doSparseCheckout + ) } class GitCommandManager { @@ -73,6 +78,7 @@ class GitCommandManager { } private gitPath = '' private lfs = false + private doSparseCheckout = false private workingDirectory = '' // Private constructor; use createCommandManager() @@ -461,10 +467,11 @@ class GitCommandManager { static async createCommandManager( workingDirectory: string, - lfs: boolean + lfs: boolean, + sparseCheckout: boolean ): Promise { const result = new GitCommandManager() - await result.initializeCommandManager(workingDirectory, lfs) + await result.initializeCommandManager(workingDirectory, lfs, sparseCheckout) return result } @@ -514,7 +521,8 @@ class GitCommandManager { private async initializeCommandManager( workingDirectory: string, - lfs: boolean + lfs: boolean, + sparseCheckout: boolean ): Promise { this.workingDirectory = workingDirectory @@ -577,6 +585,16 @@ class GitCommandManager { } } + this.doSparseCheckout = sparseCheckout + if (this.doSparseCheckout) { + // The `git sparse-checkout` command was introduced in Git v2.25.0 + const minimumGitSparseCheckoutVersion = new GitVersion('2.25') + if (!gitVersion.checkMinimum(minimumGitSparseCheckoutVersion)) { + throw new Error( + `Minimum Git version required for sparse checkout is ${minimumGitSparseCheckoutVersion}. Your git ('${this.gitPath}') is ${gitVersion}` + ) + } + } // Set the user agent const gitHttpUserAgent = `git/${gitVersion} (github-actions-checkout)` core.debug(`Set git useragent to: ${gitHttpUserAgent}`) diff --git a/src/git-source-provider.ts b/src/git-source-provider.ts index b96eb98d3..23328ebc0 100644 --- a/src/git-source-provider.ts +++ b/src/git-source-provider.ts @@ -275,7 +275,7 @@ export async function cleanup(repositoryPath: string): Promise { let git: IGitCommandManager try { - git = await gitCommandManager.createCommandManager(repositoryPath, false) + git = await gitCommandManager.createCommandManager(repositoryPath, false, false) } catch { return } @@ -311,7 +311,8 @@ async function getGitCommandManager( try { return await gitCommandManager.createCommandManager( settings.repositoryPath, - settings.lfs + settings.lfs, + settings.sparseCheckout != null ) } catch (err) { // Git is required for LFS