@@ -10,30 +10,28 @@ var program = require('commander'),
1010 WebPageTest = require ( '../lib/webpagetest' ) ,
1111 mapping = require ( '../lib/mapping' ) ;
1212
13- var command , wpt , file , ret ,
13+ var command , file , ret ,
1414 options = { } ,
1515 args = [ ] ,
16+ results = [ ] ,
1617 defaultServer = process . env . WEBPAGETEST_SERVER ||
1718 WebPageTest . defaultServer ;
1819
1920// replace default values on descriptons
2021mapping . commands . listen . info =
2122 mapping . commands . listen . info . replace ( '%s' , WebPageTest . defaultListenPort ) ;
2223
23- function output ( data , exitStatus , preExit ) {
24- if ( exitStatus ) {
25- process . stderr . write ( data ) ;
26- } else {
27- process . stdout . write ( data ) ;
28- }
24+ var output = function ( data , exitStatus , preExit ) {
25+ process . stdout . write ( data ) ;
2926 if ( typeof preExit === 'function' ) {
3027 preExit ( ) ;
3128 }
3229 process . exit ( exitStatus || 0 ) ;
33- }
30+ } ;
3431
35- var formatData = function ( err , data , info ) {
36- var encoding = 'utf8' ;
32+ var formatData = function ( err , data , info ) {
33+ var dataStr ,
34+ encoding = 'utf8' ;
3735
3836 if ( err ) {
3937 data = { error : err } ;
@@ -49,24 +47,26 @@ var formatData = function (err, data, info) {
4947
5048 if ( ! ( data instanceof Buffer ) ) {
5149 try {
52- data = JSON . stringify ( data , null , 2 ) ;
50+ dataStr = JSON . stringify ( data , null , 2 ) ;
5351 } catch ( ex ) {
54- data = JSON . stringify ( {
52+ dataStr = JSON . stringify ( {
5553 data : data . toString ( ) ,
5654 error : ex . message
5755 } , null , 2 ) ;
5856 }
5957 }
6058
6159 if ( file ) {
62- fs . writeFile ( file , data , encoding , function writeFile ( err ) {
60+ fs . writeFile ( file , dataStr , encoding , function writeFile ( err ) {
6361 if ( err ) {
6462 output ( err . message , 1 ) ;
6563 }
6664 } ) ;
6765 } else {
68- output ( data , err ? 1 : 0 ) ;
66+ output ( dataStr , err ? 1 : 0 ) ;
6967 }
68+
69+ return data ;
7070}
7171
7272function addOptions ( prg , options , nokeyList ) {
@@ -135,13 +135,13 @@ Object.keys(mapping.commands).forEach(function eachCommand(name) {
135135 }
136136
137137 defaultAction ( decodeURIComponent ( what ) , opts ) ;
138- if ( options . specs ) {
138+ if ( options . specs && ! program . batch ) {
139139 options . exitOnResults = true ;
140140 }
141141 } ,
142142 'results' : function ( id , opts ) {
143143 defaultAction ( id , opts ) ;
144- if ( opts . specs && ! program . dryrun ) {
144+ if ( opts . specs && ! program . dryrun && ! program . batch ) {
145145 formatData = null ;
146146 }
147147 } ,
@@ -158,7 +158,7 @@ Object.keys(mapping.commands).forEach(function eachCommand(name) {
158158 }
159159 } ;
160160
161- // command with (optional) parameter
161+ // command with (optional) parameter
162162 if ( cmd . param ) {
163163 if ( cmd . optional ) {
164164 openParam = '[' ;
@@ -179,10 +179,98 @@ Object.keys(mapping.commands).forEach(function eachCommand(name) {
179179 ) ;
180180} ) ;
181181
182- program . parse ( process . argv ) ;
182+ function parseBatch ( filename ) {
183+ var lines ;
183184
184- if ( command ) {
185- wpt = new WebPageTest ( program . server || defaultServer ) ;
185+ try {
186+ lines = ( fs . readFileSync ( filename , 'utf8' ) || '' )
187+ . split ( '\n' )
188+ . filter ( function ( line ) { return line ; } )
189+ . map ( function ( line ) { return line . split ( ' ' ) ; } )
190+ . map ( function ( line ) {
191+ var tmp = [ ] ;
192+ return line . reduce ( function ( prev , curr , index ) {
193+ if ( / ^ [ ^ \\ ] ? [ ' " ] / . test ( curr ) ) {
194+ tmp . push ( curr . slice ( 1 ) ) ;
195+ } else if ( tmp . length ) {
196+ if ( / [ ^ \\ ] [ ' " ] $ / . test ( curr ) ) {
197+ tmp . push ( curr . slice ( 0 , curr . length - 1 ) ) ;
198+ prev . push ( tmp . join ( ' ' ) ) ;
199+ tmp = [ ] ;
200+ } else {
201+ tmp . push ( curr ) ;
202+ }
203+ } else {
204+ prev . push ( curr ) ;
205+ }
206+ return prev ;
207+ } , [ '' , '' ] ) ;
208+ } ) ;
209+ } catch ( err ) {
210+ output ( err . message + '\n' , 1 ) ;
211+ }
212+
213+ return lines ;
214+ }
215+ //return console.log(parseBatch('batch.txt'));
216+
217+ function batch ( file ) {
218+ var accErr ,
219+ count = 2 ,
220+ originalFormatData = formatData ,
221+ originalOutput = output ;
222+
223+ function checkDone ( ) {
224+ count -- ;
225+ if ( ! count ) {
226+ originalOutput (
227+ results . length ? JSON . stringify ( results , null , 2 ) : '' ,
228+ accErr ? 1 : 0
229+ ) ;
230+ }
231+ } ;
232+
233+ function checkError ( err ) {
234+ accErr = accErr || err ;
235+ checkDone ( ) ;
236+ }
237+
238+ function aggregate ( index , err , data , info ) {
239+ results [ index ] = originalFormatData ( err , data , info ) ;
240+ checkError ( err ) ;
241+ }
242+
243+ program . batch = true ;
244+ var cmds = parseBatch ( file ) ;
245+ if ( ! cmds ) {
246+ return ;
247+ }
248+ output = function ( ) { } ;
249+
250+ cmds . forEach ( function ( cmd , index ) {
251+ program . parse ( cmd ) ;
252+ formatData = options . specs ? checkError : aggregate . bind ( null , index ) ;
253+ execCommand ( ) ;
254+ cleanupProgram ( ) ;
255+ } ) ;
256+ }
257+
258+ function cleanupProgram ( ) {
259+ command = null ;
260+ options = { } ;
261+ args = [ ] ;
262+ program . commands . forEach ( function ( c ) {
263+ c . options . forEach ( function ( o ) {
264+ delete c [ o . long . slice ( 2 ) ] ;
265+ } ) ;
266+ } ) ;
267+ delete program . server ;
268+ delete program . dryrun ;
269+ delete program . out ;
270+ }
271+
272+ function execCommand ( ) {
273+ var wpt = new WebPageTest ( program . server || defaultServer ) ;
186274
187275 // options
188276 if ( options ) {
@@ -198,7 +286,19 @@ if (command) {
198286 file = program . out ;
199287
200288 wpt [ command ] . apply ( wpt , args ) ;
201- } else {
289+ }
290+
291+ program
292+ . command ( 'batch <file>' )
293+ . description (
294+ 'run commands in batch, i.e. one command per line from <file> in parallel' )
295+ . action ( batch ) ;
296+
297+ program . parse ( process . argv ) ;
298+
299+ if ( command ) {
300+ execCommand ( ) ;
301+ } else if ( ! program . batch ) {
202302 output ( program . helpInformation ( ) , 1 , function defaultHelp ( ) {
203303 program . emit ( '--help' ) ;
204304 } ) ;
0 commit comments