Skip to content

Commit

Permalink
fix(core): standardize chunking elements passing to cli (#15322)
Browse files Browse the repository at this point in the history
  • Loading branch information
AgentEnder committed Mar 2, 2023
1 parent 8268207 commit bf08714
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 29 deletions.
11 changes: 2 additions & 9 deletions packages/nx/src/command-line/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { createProjectGraphAsync } from '../project-graph/project-graph';
import { filterAffected } from '../project-graph/affected/affected-project-graph';
import { readNxJson } from '../config/configuration';
import { ProjectGraph } from '../config/project-graph';
import { chunkify } from '../utils/chunkify';

const PRETTIER_PATH = require.resolve('prettier/bin-prettier');

Expand All @@ -40,7 +41,7 @@ export async function format(
);

// Chunkify the patterns array to prevent crashing the windows terminal
const chunkList: string[][] = chunkify(patterns, 50);
const chunkList: string[][] = chunkify(patterns);

switch (command) {
case 'write':
Expand Down Expand Up @@ -143,14 +144,6 @@ function getPatternsFromProjects(
return getProjectRoots(projects, projectGraph);
}

function chunkify(target: string[], size: number): string[][] {
return target.reduce((current: string[][], value: string, index: number) => {
if (index % size === 0) current.push([]);
current[current.length - 1].push(value);
return current;
}, []);
}

function write(patterns: string[]) {
if (patterns.length > 0) {
const [swcrcPatterns, regularPatterns] = patterns.reduce(
Expand Down
24 changes: 4 additions & 20 deletions packages/nx/src/hasher/git-hasher.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { spawn } from 'child_process';
import { chunkify } from '../utils/chunkify';
import { fileExists } from '../utils/fileutils';
import { joinPathFragments } from '../utils/path';

Expand All @@ -12,26 +13,9 @@ export async function getGitHashForFiles(
);

const res: Map<string, string> = new Map<string, string>();
const promises: Promise<Map<string, string>>[] = [];
if (filesToHash.length) {
// On windows the max length is limited by the length of
// the overall comand, rather than the number of individual
// arguments. Since file paths are large and rather variable,
// we use a smaller batchSize.
const batchSize = process.platform === 'win32' ? 250 : 4000;
for (
let startIndex = 0;
startIndex < filesToHash.length;
startIndex += batchSize
) {
promises.push(
getGitHashForBatch(
filesToHash.slice(startIndex, startIndex + batchSize),
path
)
);
}
}
const promises: Promise<Map<string, string>>[] = chunkify(filesToHash).map(
(files) => getGitHashForBatch(files, path)
);
// Merge batch results into final result set
const batchResults = await Promise.all(promises);
for (const batch of batchResults) {
Expand Down
15 changes: 15 additions & 0 deletions packages/nx/src/utils/chunkify.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { chunkify } from './chunkify';

describe('chunkify', () => {
it('should wrap chunks at passed in size', () => {
const files = ['aa', 'bb', 'cc', 'dd', 'ee'];
expect(chunkify(files, 4)).toHaveLength(5);
expect(chunkify(files, 7)).toHaveLength(3);
expect(chunkify(files, 16)).toHaveLength(1);
});

it('should contain all items from target', () => {
const files = ['aa', 'bb', 'cc', 'dd', 'ee'];
expect(chunkify(files, 7).flat()).toHaveLength(5);
});
});
41 changes: 41 additions & 0 deletions packages/nx/src/utils/chunkify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { execSync } from 'child_process';

const TERMINAL_SIZE =
process.platform === 'win32' ? 8192 : getUnixTerminalSize();

export function chunkify(
target: string[],
maxChunkLength: number = TERMINAL_SIZE - 500
): string[][] {
const chunks = [];
let currentChunk = [];
let currentChunkLength = 0;
for (const file of target) {
if (
// Prevent empty chunk if first file path is longer than maxChunkLength
currentChunk.length &&
// +1 accounts for the space between file names
currentChunkLength + file.length + 1 >= maxChunkLength
) {
chunks.push(currentChunk);
currentChunk = [];
currentChunkLength = 0;
}
currentChunk.push(file);
currentChunkLength += file.length + 1;
}
chunks.push(currentChunk);
return chunks;
}

function getUnixTerminalSize() {
try {
const argMax = execSync('getconf ARG_MAX').toString().trim();
return Number.parseInt(argMax);
} catch {
// This number varies by system, but 100k seems like a safe
// number from some research...
// https://stackoverflow.com/questions/19354870/bash-command-line-and-input-limit
return 100000;
}
}

1 comment on commit bf08714

@vercel
Copy link

@vercel vercel bot commented on bf08714 Mar 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-dev-nrwl.vercel.app
nx-five.vercel.app
nx-dev-git-master-nrwl.vercel.app
nx.dev

Please sign in to comment.