@@ -10,6 +10,8 @@ import { buildCmdExeCommandLine } from "./windows-cmd-helpers.mjs";
1010
1111const ROOT = path . resolve ( import . meta. dirname , ".." ) ;
1212const OXFMT_CONFIG = path . join ( ROOT , ".oxfmtrc.jsonc" ) ;
13+ const WINDOWS_CMD_EXE_MAX_COMMAND_LINE_LENGTH = 8191 ;
14+ const WINDOWS_CMD_EXE_COMMAND_LINE_BUDGET = 7600 ;
1315
1416function childFailureMessage ( commandName , result ) {
1517 if ( result . error ) {
@@ -63,13 +65,65 @@ export function createOxfmtSpawnSpec(args, params = {}) {
6365 } ;
6466}
6567
66- export function runOxfmt ( files , params = { } ) {
68+ function oxfmtArgs ( files , params = { } ) {
69+ return [ "--write" , "--threads=1" , "--config" , params . config ?? OXFMT_CONFIG , ...files ] ;
70+ }
71+
72+ function commandLineLength ( spec ) {
73+ return [ spec . command , ...spec . args ] . join ( " " ) . length ;
74+ }
75+
76+ export function oxfmtFileBatches ( files , params = { } ) {
77+ const platform = params . platform ?? process . platform ;
78+ if ( platform !== "win32" ) {
79+ return [ files ] ;
80+ }
81+
82+ const maxLength = params . maxWindowsCommandLineLength ?? WINDOWS_CMD_EXE_COMMAND_LINE_BUDGET ;
83+ if ( maxLength > WINDOWS_CMD_EXE_MAX_COMMAND_LINE_LENGTH ) {
84+ throw new Error (
85+ `Windows oxfmt command line budget ${ maxLength } exceeds cmd.exe limit ${ WINDOWS_CMD_EXE_MAX_COMMAND_LINE_LENGTH } ` ,
86+ ) ;
87+ }
88+
89+ const batches = [ ] ;
90+ let batch = [ ] ;
91+ for ( const file of files ) {
92+ const candidate = [ ...batch , file ] ;
93+ const candidateLength = commandLineLength (
94+ createOxfmtSpawnSpec ( oxfmtArgs ( candidate , params ) , params ) ,
95+ ) ;
96+ if ( candidateLength <= maxLength ) {
97+ batch = candidate ;
98+ continue ;
99+ }
100+
101+ if ( batch . length === 0 ) {
102+ throw new Error (
103+ `Windows oxfmt command line is too long for one docs file: ${ file } (${ candidateLength } characters)` ,
104+ ) ;
105+ }
106+
107+ batches . push ( batch ) ;
108+ const singleLength = commandLineLength ( createOxfmtSpawnSpec ( oxfmtArgs ( [ file ] , params ) , params ) ) ;
109+ if ( singleLength > maxLength ) {
110+ throw new Error (
111+ `Windows oxfmt command line is too long for one docs file: ${ file } (${ singleLength } characters)` ,
112+ ) ;
113+ }
114+ batch = [ file ] ;
115+ }
116+
117+ if ( batch . length > 0 ) {
118+ batches . push ( batch ) ;
119+ }
120+ return batches ;
121+ }
122+
123+ function runOxfmtBatch ( files , params = { } ) {
67124 const root = params . root ?? ROOT ;
68125 const spawnSyncImpl = params . spawnSync ?? spawnSync ;
69- const spec = createOxfmtSpawnSpec (
70- [ "--write" , "--threads=1" , "--config" , params . config ?? OXFMT_CONFIG , ...files ] ,
71- params ,
72- ) ;
126+ const spec = createOxfmtSpawnSpec ( oxfmtArgs ( files , params ) , params ) ;
73127 const result = spawnSyncImpl ( spec . command , spec . args , {
74128 cwd : root ,
75129 encoding : "utf8" ,
@@ -82,6 +136,12 @@ export function runOxfmt(files, params = {}) {
82136 }
83137}
84138
139+ export function runOxfmt ( files , params = { } ) {
140+ for ( const batch of oxfmtFileBatches ( files , params ) ) {
141+ runOxfmtBatch ( batch , params ) ;
142+ }
143+ }
144+
85145function repairFiles ( root , files ) {
86146 const changed = [ ] ;
87147 for ( const relativePath of files ) {
0 commit comments