From e3e36c7b62f6570130d976e8553844c9152a11c9 Mon Sep 17 00:00:00 2001 From: Riley Martine Date: Fri, 3 May 2024 16:31:28 -0600 Subject: [PATCH 1/4] Abort `sl root` call if output resembles a steam locomotive Jest detects whether a repository is a sapling repo by calling the `sl` binary, and getting the output. If `sl` (steam locomotive) is installed, the output of `sl root` 1) takes forever to get and 2) is not the root, but a moving image of a steam locomotive. This change monitors the stdout stream, and aborts the `sl` call if the first character is an escape character, which indicates that the terminal is being cleared to make way for a train to come through. See also: https://github.com/jestjs/jest/issues/14046 --- packages/jest-changed-files/src/sl.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/jest-changed-files/src/sl.ts b/packages/jest-changed-files/src/sl.ts index 50ee99122757..697609c18975 100644 --- a/packages/jest-changed-files/src/sl.ts +++ b/packages/jest-changed-files/src/sl.ts @@ -56,7 +56,28 @@ const adapter: SCMAdapter = { getRoot: async cwd => { try { - const result = await execa('sl', ['root'], {cwd, env}); + const subprocess = execa('sl', ['root'], {cwd, env}); + if (subprocess.stdout == null) { + return null; + } + + // Check if we're calling sl (steam locomotive) instead of sl (sapling) + // by looking for the escape character in the first chunk of data. + let firstChunk = true; + subprocess.stdout.on('data', data => { + if (!firstChunk) { + return; + } + if (data.toString().codePointAt(0) === 27) { + subprocess.cancel(); + } + firstChunk = false; + }); + + const result = await subprocess; + if (result.killed) { + return null; + } return result.stdout; } catch { From 37737fce4c9ae86a21ba3278443c0951982e3424 Mon Sep 17 00:00:00 2001 From: Riley Martine Date: Fri, 3 May 2024 18:23:51 -0600 Subject: [PATCH 2/4] fix typescript errors --- CHANGELOG.md | 1 + packages/jest-changed-files/src/sl.ts | 21 ++++++++------------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 070258d7a0b3..412c978eb3a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ - `[babel-plugin-jest-hoist]` Use `denylist` instead of the deprecated `blacklist` for Babel 8 support ([#14109](https://github.com/jestjs/jest/pull/14109)) - `[expect]` Check error instance type for `toThrow/toThrowError` ([#14576](https://github.com/jestjs/jest/pull/14576)) +- `[jest-changed-files]` Abort `sl root` call if output resembles a steam locomotive ([#15053](https://github.com/jestjs/jest/pull/15053)) - `[jest-circus]` [**BREAKING**] Prevent false test failures caused by promise rejections handled asynchronously ([#14315](https://github.com/jestjs/jest/pull/14315)) - `[jest-circus]` Replace recursive `makeTestResults` implementation with iterative one ([#14760](https://github.com/jestjs/jest/pull/14760)) - `[jest-circus]` Omit `expect.hasAssertions()` errors if a test already has errors ([#14866](https://github.com/jestjs/jest/pull/14866)) diff --git a/packages/jest-changed-files/src/sl.ts b/packages/jest-changed-files/src/sl.ts index 697609c18975..3530493d0200 100644 --- a/packages/jest-changed-files/src/sl.ts +++ b/packages/jest-changed-files/src/sl.ts @@ -57,22 +57,17 @@ const adapter: SCMAdapter = { getRoot: async cwd => { try { const subprocess = execa('sl', ['root'], {cwd, env}); - if (subprocess.stdout == null) { - return null; - } // Check if we're calling sl (steam locomotive) instead of sl (sapling) // by looking for the escape character in the first chunk of data. - let firstChunk = true; - subprocess.stdout.on('data', data => { - if (!firstChunk) { - return; - } - if (data.toString().codePointAt(0) === 27) { - subprocess.cancel(); - } - firstChunk = false; - }); + if (subprocess.stdout) { + subprocess.stdout.once('data', (data: Buffer | string) => { + data = Buffer.isBuffer(data) ? data.toString() : data; + if (data.codePointAt(0) === 27) { + subprocess.cancel(); + } + }); + } const result = await subprocess; if (result.killed) { From f4a2c130a9db14fcf94e27fc9bb05437f00695f0 Mon Sep 17 00:00:00 2001 From: Riley Martine Date: Mon, 6 May 2024 20:11:59 -0600 Subject: [PATCH 3/4] spawn fewer locomotives in projects with many roots --- packages/jest-changed-files/src/sl.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/jest-changed-files/src/sl.ts b/packages/jest-changed-files/src/sl.ts index 3530493d0200..c0553c6a2e1b 100644 --- a/packages/jest-changed-files/src/sl.ts +++ b/packages/jest-changed-files/src/sl.ts @@ -17,6 +17,9 @@ import type {SCMAdapter} from './types'; */ const env = {...process.env, HGPLAIN: '1'}; +// Whether `sl` is a steam locomotive or not +let isSteamLocomotive = false; + const adapter: SCMAdapter = { findChangedFiles: async (cwd, options) => { const includePaths = options.includePaths ?? []; @@ -55,6 +58,10 @@ const adapter: SCMAdapter = { }, getRoot: async cwd => { + if (isSteamLocomotive) { + return null; + } + try { const subprocess = execa('sl', ['root'], {cwd, env}); @@ -65,6 +72,7 @@ const adapter: SCMAdapter = { data = Buffer.isBuffer(data) ? data.toString() : data; if (data.codePointAt(0) === 27) { subprocess.cancel(); + isSteamLocomotive = true; } }); } From b06121a3584c0cd797e939a3963e145f6b9490af Mon Sep 17 00:00:00 2001 From: Riley Martine Date: Wed, 8 May 2024 15:54:56 -0600 Subject: [PATCH 4/4] Update packages/jest-changed-files/src/sl.ts Co-authored-by: Simen Bekkhus --- packages/jest-changed-files/src/sl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-changed-files/src/sl.ts b/packages/jest-changed-files/src/sl.ts index be999b31f724..09f7162107ed 100644 --- a/packages/jest-changed-files/src/sl.ts +++ b/packages/jest-changed-files/src/sl.ts @@ -65,7 +65,7 @@ const adapter: SCMAdapter = { } const result = await subprocess; - if (result.killed) { + if (result.killed && isSteamLocomotive) { return null; }