ソースを参照

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
John Wesley Walker III 1 年間 前
コミット
cd7d8d697e

+ 2 - 1
__test__/git-auth-helper.test.ts

@@ -796,7 +796,8 @@ async function setup(testName: string): Promise<void> {
     ),
     tryDisableAutomaticGarbageCollection: jest.fn(),
     tryGetFetchUrl: jest.fn(),
-    tryReset: jest.fn()
+    tryReset: jest.fn(),
+    version: jest.fn()
   }
 
   settings = {

+ 2 - 1
__test__/git-directory-helper.test.ts

@@ -501,6 +501,7 @@ async function setup(testName: string): Promise<void> {
     }),
     tryReset: jest.fn(async () => {
       return true
-    })
+    }),
+    version: jest.fn()
   }
 }

+ 42 - 1
__test__/git-version.test.ts

@@ -1,4 +1,5 @@
-import {GitVersion} from '../lib/git-version'
+import {GitVersion} from '../src/git-version'
+import {MinimumGitSparseCheckoutVersion} from '../src/git-command-manager'
 
 describe('git-version tests', () => {
   it('basics', async () => {
@@ -42,4 +43,44 @@ describe('git-version tests', () => {
     expect(version.checkMinimum(new GitVersion('5.1'))).toBeFalsy()
     expect(version.checkMinimum(new GitVersion('5.1.2'))).toBeFalsy()
   })
+
+  it('sparse checkout', async () => {
+    const minSparseVer = MinimumGitSparseCheckoutVersion
+    expect(new GitVersion('1.0').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('1.99').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.0').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.24').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.24.0').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.24.9').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.25').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.25.0').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.25.1').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.25.9').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.26').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.26.0').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.26.1').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.26.9').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.27').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.27.0').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.27.1').checkMinimum(minSparseVer)).toBeFalsy()
+    expect(new GitVersion('2.27.9').checkMinimum(minSparseVer)).toBeFalsy()
+    //                             /---------------------------------------
+    //         ^^^ before         /         after vvv
+    // --------------------------/
+    expect(new GitVersion('2.28').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('2.28.0').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('2.28.1').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('2.28.9').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('2.29').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('2.29.0').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('2.29.1').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('2.29.9').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('2.99').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('3.0').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('3.99').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('4.0').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('4.99').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('5.0').checkMinimum(minSparseVer)).toBeTruthy()
+    expect(new GitVersion('5.99').checkMinimum(minSparseVer)).toBeTruthy()
+  })
 })

+ 23 - 12
dist/index.js

@@ -467,7 +467,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
     });
 };
 Object.defineProperty(exports, "__esModule", ({ value: true }));
-exports.createCommandManager = exports.MinimumGitVersion = void 0;
+exports.createCommandManager = exports.MinimumGitSparseCheckoutVersion = exports.MinimumGitVersion = void 0;
 const core = __importStar(__nccwpck_require__(2186));
 const exec = __importStar(__nccwpck_require__(1514));
 const fs = __importStar(__nccwpck_require__(7147));
@@ -480,7 +480,9 @@ const retryHelper = __importStar(__nccwpck_require__(2155));
 const git_version_1 = __nccwpck_require__(3142);
 // Auth header not supported before 2.9
 // Wire protocol v2 not supported before 2.18
+// sparse-checkout not [well-]supported before 2.28 (see https://github.com/actions/checkout/issues/1386)
 exports.MinimumGitVersion = new git_version_1.GitVersion('2.18');
+exports.MinimumGitSparseCheckoutVersion = new git_version_1.GitVersion('2.28');
 function createCommandManager(workingDirectory, lfs, doSparseCheckout) {
     return __awaiter(this, void 0, void 0, function* () {
         return yield GitCommandManager.createCommandManager(workingDirectory, lfs, doSparseCheckout);
@@ -498,6 +500,7 @@ class GitCommandManager {
         this.lfs = false;
         this.doSparseCheckout = false;
         this.workingDirectory = '';
+        this.gitVersion = new git_version_1.GitVersion();
     }
     branchDelete(remote, branch) {
         return __awaiter(this, void 0, void 0, function* () {
@@ -850,6 +853,11 @@ class GitCommandManager {
             return output.exitCode === 0;
         });
     }
+    version() {
+        return __awaiter(this, void 0, void 0, function* () {
+            return this.gitVersion;
+        });
+    }
     static createCommandManager(workingDirectory, lfs, doSparseCheckout) {
         return __awaiter(this, void 0, void 0, function* () {
             const result = new GitCommandManager();
@@ -901,21 +909,21 @@ class GitCommandManager {
             this.gitPath = yield io.which('git', true);
             // Git version
             core.debug('Getting git version');
-            let gitVersion = new git_version_1.GitVersion();
+            this.gitVersion = new git_version_1.GitVersion();
             let gitOutput = yield this.execGit(['version']);
             let stdout = gitOutput.stdout.trim();
             if (!stdout.includes('\n')) {
                 const match = stdout.match(/\d+\.\d+(\.\d+)?/);
                 if (match) {
-                    gitVersion = new git_version_1.GitVersion(match[0]);
+                    this.gitVersion = new git_version_1.GitVersion(match[0]);
                 }
             }
-            if (!gitVersion.isValid()) {
+            if (!this.gitVersion.isValid()) {
                 throw new Error('Unable to determine git version');
             }
             // Minimum git version
-            if (!gitVersion.checkMinimum(exports.MinimumGitVersion)) {
-                throw new Error(`Minimum required git version is ${exports.MinimumGitVersion}. Your git ('${this.gitPath}') is ${gitVersion}`);
+            if (!this.gitVersion.checkMinimum(exports.MinimumGitVersion)) {
+                throw new Error(`Minimum required git version is ${exports.MinimumGitVersion}. Your git ('${this.gitPath}') is ${this.gitVersion}`);
             }
             if (this.lfs) {
                 // Git-lfs version
@@ -943,14 +951,12 @@ class GitCommandManager {
             }
             this.doSparseCheckout = doSparseCheckout;
             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}`);
+                if (!this.gitVersion.checkMinimum(exports.MinimumGitSparseCheckoutVersion)) {
+                    throw new Error(`Minimum Git version required for sparse checkout is ${exports.MinimumGitSparseCheckoutVersion}. Your git ('${this.gitPath}') is ${this.gitVersion}`);
                 }
             }
             // Set the user agent
-            const gitHttpUserAgent = `git/${gitVersion} (github-actions-checkout)`;
+            const gitHttpUserAgent = `git/${this.gitVersion} (github-actions-checkout)`;
             core.debug(`Set git useragent to: ${gitHttpUserAgent}`);
             this.gitEnv['GIT_HTTP_USER_AGENT'] = gitHttpUserAgent;
         });
@@ -1155,6 +1161,7 @@ const path = __importStar(__nccwpck_require__(1017));
 const refHelper = __importStar(__nccwpck_require__(8601));
 const stateHelper = __importStar(__nccwpck_require__(8647));
 const urlHelper = __importStar(__nccwpck_require__(9437));
+const git_command_manager_1 = __nccwpck_require__(738);
 function getSource(settings) {
     return __awaiter(this, void 0, void 0, function* () {
         // Repository URL
@@ -1288,7 +1295,11 @@ function getSource(settings) {
             }
             // Sparse checkout
             if (!settings.sparseCheckout) {
-                yield git.disableSparseCheckout();
+                let gitVersion = yield git.version();
+                // no need to disable sparse-checkout if the installed git runtime doesn't even support it.
+                if (gitVersion.checkMinimum(git_command_manager_1.MinimumGitSparseCheckoutVersion)) {
+                    yield git.disableSparseCheckout();
+                }
             }
             else {
                 core.startGroup('Setting up sparse checkout');

+ 2 - 2
package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "checkout",
-  "version": "4.1.2",
+  "version": "4.1.3",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "checkout",
-      "version": "4.1.2",
+      "version": "4.1.3",
       "license": "MIT",
       "dependencies": {
         "@actions/core": "^1.10.0",

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "checkout",
-  "version": "4.1.2",
+  "version": "4.1.3",
   "description": "checkout action",
   "main": "lib/main.js",
   "scripts": {

+ 16 - 10
src/git-command-manager.ts

@@ -11,7 +11,9 @@ import {GitVersion} from './git-version'
 
 // Auth header not supported before 2.9
 // Wire protocol v2 not supported before 2.18
+// sparse-checkout not [well-]supported before 2.28 (see https://github.com/actions/checkout/issues/1386)
 export const MinimumGitVersion = new GitVersion('2.18')
+export const MinimumGitSparseCheckoutVersion = new GitVersion('2.28')
 
 export interface IGitCommandManager {
   branchDelete(remote: boolean, branch: string): Promise<void>
@@ -60,6 +62,7 @@ export interface IGitCommandManager {
   tryDisableAutomaticGarbageCollection(): Promise<boolean>
   tryGetFetchUrl(): Promise<string>
   tryReset(): Promise<boolean>
+  version(): Promise<GitVersion>
 }
 
 export async function createCommandManager(
@@ -83,6 +86,7 @@ class GitCommandManager {
   private lfs = false
   private doSparseCheckout = false
   private workingDirectory = ''
+  private gitVersion: GitVersion = new GitVersion()
 
   // Private constructor; use createCommandManager()
   private constructor() {}
@@ -480,6 +484,10 @@ class GitCommandManager {
     return output.exitCode === 0
   }
 
+  async version(): Promise<GitVersion> {
+    return this.gitVersion
+  }
+
   static async createCommandManager(
     workingDirectory: string,
     lfs: boolean,
@@ -556,23 +564,23 @@ class GitCommandManager {
 
     // Git version
     core.debug('Getting git version')
-    let gitVersion = new GitVersion()
+    this.gitVersion = new GitVersion()
     let gitOutput = await this.execGit(['version'])
     let stdout = gitOutput.stdout.trim()
     if (!stdout.includes('\n')) {
       const match = stdout.match(/\d+\.\d+(\.\d+)?/)
       if (match) {
-        gitVersion = new GitVersion(match[0])
+        this.gitVersion = new GitVersion(match[0])
       }
     }
-    if (!gitVersion.isValid()) {
+    if (!this.gitVersion.isValid()) {
       throw new Error('Unable to determine git version')
     }
 
     // Minimum git version
-    if (!gitVersion.checkMinimum(MinimumGitVersion)) {
+    if (!this.gitVersion.checkMinimum(MinimumGitVersion)) {
       throw new Error(
-        `Minimum required git version is ${MinimumGitVersion}. Your git ('${this.gitPath}') is ${gitVersion}`
+        `Minimum required git version is ${MinimumGitVersion}. Your git ('${this.gitPath}') is ${this.gitVersion}`
       )
     }
 
@@ -606,16 +614,14 @@ class GitCommandManager {
 
     this.doSparseCheckout = doSparseCheckout
     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)) {
+      if (!this.gitVersion.checkMinimum(MinimumGitSparseCheckoutVersion)) {
         throw new Error(
-          `Minimum Git version required for sparse checkout is ${minimumGitSparseCheckoutVersion}. Your git ('${this.gitPath}') is ${gitVersion}`
+          `Minimum Git version required for sparse checkout is ${MinimumGitSparseCheckoutVersion}. Your git ('${this.gitPath}') is ${this.gitVersion}`
         )
       }
     }
     // Set the user agent
-    const gitHttpUserAgent = `git/${gitVersion} (github-actions-checkout)`
+    const gitHttpUserAgent = `git/${this.gitVersion} (github-actions-checkout)`
     core.debug(`Set git useragent to: ${gitHttpUserAgent}`)
     this.gitEnv['GIT_HTTP_USER_AGENT'] = gitHttpUserAgent
   }

+ 9 - 2
src/git-source-provider.ts

@@ -9,7 +9,10 @@ import * as path from 'path'
 import * as refHelper from './ref-helper'
 import * as stateHelper from './state-helper'
 import * as urlHelper from './url-helper'
-import {IGitCommandManager} from './git-command-manager'
+import {
+  MinimumGitSparseCheckoutVersion,
+  IGitCommandManager
+} from './git-command-manager'
 import {IGitSourceSettings} from './git-source-settings'
 
 export async function getSource(settings: IGitSourceSettings): Promise<void> {
@@ -209,7 +212,11 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
 
     // Sparse checkout
     if (!settings.sparseCheckout) {
-      await git.disableSparseCheckout()
+      let gitVersion = await git.version()
+      // no need to disable sparse-checkout if the installed git runtime doesn't even support it.
+      if (gitVersion.checkMinimum(MinimumGitSparseCheckoutVersion)) {
+        await git.disableSparseCheckout()
+      }
     } else {
       core.startGroup('Setting up sparse checkout')
       if (settings.sparseCheckoutConeMode) {