1- let npm // set by the cli
2- let cbCalled = false
31const log = require ( 'npmlog' )
4- let itWorked = false
2+ const os = require ( 'os' )
53const path = require ( 'path' )
64const writeFileAtomic = require ( 'write-file-atomic' )
75const mkdirp = require ( 'mkdirp-infer-owner' )
86const fs = require ( 'graceful-fs' )
9- let wroteLogFile = false
10- let exitCode = 0
7+
118const errorMessage = require ( './error-message.js' )
129const replaceInfo = require ( './replace-info.js' )
1310
11+ let exitHandlerCalled = false
1412let logFileName
13+ let npm // set by the cli
14+ let wroteLogFile = false
15+
16+ const timings = { }
17+
1518const getLogFile = ( ) => {
1619 // we call this multiple times, so we need to treat it as a singleton because
1720 // the date is part of the name
@@ -21,7 +24,6 @@ const getLogFile = () => {
2124 return logFileName
2225}
2326
24- const timings = { }
2527process . on ( 'timing' , ( name , value ) => {
2628 if ( timings [ name ] )
2729 timings [ name ] += value
@@ -53,22 +55,20 @@ process.on('exit', code => {
5355 }
5456 }
5557
56- if ( code )
57- itWorked = false
58- if ( itWorked )
58+ if ( ! code )
5959 log . info ( 'ok' )
6060 else {
61- if ( ! cbCalled ) {
62- log . error ( '' , 'cb() never called!' )
61+ if ( ! exitHandlerCalled ) {
62+ log . error ( '' , 'Exit handler never called!' )
6363 console . error ( '' )
6464 log . error ( '' , 'This is an error with npm itself. Please report this error at:' )
6565 log . error ( '' , ' <https://github.com/npm/cli/issues>' )
66+ // TODO this doesn't have an npm.config.loaded guard
6667 writeLogFile ( )
6768 }
68-
69- if ( code )
70- log . verbose ( 'code' , code )
69+ log . verbose ( 'code' , code )
7170 }
71+ // In timing mode we always write the log file
7272 if ( npm . config && npm . config . loaded && npm . config . get ( 'timing' ) && ! wroteLogFile )
7373 writeLogFile ( )
7474 if ( wroteLogFile ) {
@@ -83,52 +83,46 @@ process.on('exit', code => {
8383 ' ' + getLogFile ( ) ,
8484 ] . join ( '\n' )
8585 )
86- wroteLogFile = false
8786 }
8887
89- // actually exit.
90- if ( exitCode === 0 && ! itWorked )
91- exitCode = 1
88+ // these are needed for the tests to have a clean slate in each test case
89+ exitHandlerCalled = false
90+ wroteLogFile = false
9291
93- if ( exitCode !== 0 )
94- process . exit ( exitCode )
92+ // actually exit.
93+ process . exit ( code )
9594} )
9695
9796const exit = ( code , noLog ) => {
98- exitCode = exitCode || process . exitCode || code
99-
100- log . verbose ( 'exit' , code )
97+ log . verbose ( 'exit' , code || 0 )
10198 if ( log . level === 'silent' )
10299 noLog = true
103100
104- const reallyExit = ( ) => {
105- itWorked = ! code
106-
107- // Exit directly -- nothing in the CLI should still be running in the
108- // background at this point, and this makes sure anything left dangling
109- // for whatever reason gets thrown away, instead of leaving the CLI open
110- //
111- // Commands that expect long-running actions should just delay `cb()`
112- process . stdout . write ( '' , ( ) => {
113- process . exit ( code )
114- } )
115- }
116-
101+ // noLog is true if there was an error, including if config wasn't loaded, so
102+ // this doesn't need a config.loaded guard
117103 if ( code && ! noLog )
118104 writeLogFile ( )
119- reallyExit ( )
105+
106+ // Exit directly -- nothing in the CLI should still be running in the
107+ // background at this point, and this makes sure anything left dangling
108+ // for whatever reason gets thrown away, instead of leaving the CLI open
109+ process . stdout . write ( '' , ( ) => {
110+ // `|| process.exitCode` supports a single use case, where we set the exit
111+ // code to 1 if npm is called with no arguments
112+ process . exit ( code )
113+ } )
120114}
121115
122- const errorHandler = ( er ) => {
116+ const exitHandler = ( err ) => {
123117 log . disableProgress ( )
124118 if ( ! npm . config || ! npm . config . loaded ) {
125119 // logging won't work unless we pretend that it's ready
126- er = er || new Error ( 'Exit prior to config file resolving.' )
127- console . error ( er . stack || er . message )
120+ err = err || new Error ( 'Exit prior to config file resolving.' )
121+ console . error ( err . stack || err . message )
128122 }
129123
130- if ( cbCalled )
131- er = er || new Error ( 'Callback called more than once.' )
124+ if ( exitHandlerCalled )
125+ err = err || new Error ( 'Exit handler called more than once.' )
132126
133127 // only show the notification if it finished before the other stuff we
134128 // were doing. no need to hang on `npm -v` or something.
@@ -139,68 +133,67 @@ const errorHandler = (er) => {
139133 log . level = level
140134 }
141135
142- cbCalled = true
143- if ( ! er )
144- return exit ( 0 )
136+ exitHandlerCalled = true
137+ if ( ! err )
138+ return exit ( )
145139
146140 // if we got a command that just shells out to something else, then it
147141 // will presumably print its own errors and exit with a proper status
148142 // code if there's a problem. If we got an error with a code=0, then...
149143 // something else went wrong along the way, so maybe an npm problem?
150144 const isShellout = npm . shelloutCommands . includes ( npm . command )
151- const quietShellout = isShellout && typeof er . code === 'number' && er . code
145+ const quietShellout = isShellout && typeof err . code === 'number' && err . code
152146 if ( quietShellout )
153- return exit ( er . code , true )
154- else if ( typeof er === 'string' ) {
155- log . error ( '' , er )
147+ return exit ( err . code , true )
148+ else if ( typeof err === 'string' ) {
149+ log . error ( '' , err )
156150 return exit ( 1 , true )
157- } else if ( ! ( er instanceof Error ) ) {
158- log . error ( 'weird error' , er )
151+ } else if ( ! ( err instanceof Error ) ) {
152+ log . error ( 'weird error' , err )
159153 return exit ( 1 , true )
160154 }
161155
162- if ( ! er . code ) {
163- const matchErrorCode = er . message . match ( / ^ (?: E r r o r : ) ? ( E [ A - Z ] + ) / )
164- er . code = matchErrorCode && matchErrorCode [ 1 ]
156+ if ( ! err . code ) {
157+ const matchErrorCode = err . message . match ( / ^ (?: E r r o r : ) ? ( E [ A - Z ] + ) / )
158+ err . code = matchErrorCode && matchErrorCode [ 1 ]
165159 }
166160
167161 for ( const k of [ 'type' , 'stack' , 'statusCode' , 'pkgid' ] ) {
168- const v = er [ k ]
162+ const v = err [ k ]
169163 if ( v )
170164 log . verbose ( k , replaceInfo ( v ) )
171165 }
172166
173167 log . verbose ( 'cwd' , process . cwd ( ) )
174168
175- const os = require ( 'os' )
176169 const args = replaceInfo ( process . argv )
177170 log . verbose ( '' , os . type ( ) + ' ' + os . release ( ) )
178171 log . verbose ( 'argv' , args . map ( JSON . stringify ) . join ( ' ' ) )
179172 log . verbose ( 'node' , process . version )
180173 log . verbose ( 'npm ' , 'v' + npm . version )
181174
182175 for ( const k of [ 'code' , 'syscall' , 'file' , 'path' , 'dest' , 'errno' ] ) {
183- const v = er [ k ]
176+ const v = err [ k ]
184177 if ( v )
185178 log . error ( k , v )
186179 }
187180
188- const msg = errorMessage ( er , npm )
181+ const msg = errorMessage ( err , npm )
189182 for ( const errline of [ ...msg . summary , ...msg . detail ] )
190183 log . error ( ...errline )
191184
192185 if ( npm . config && npm . config . get ( 'json' ) ) {
193186 const error = {
194187 error : {
195- code : er . code ,
188+ code : err . code ,
196189 summary : messageText ( msg . summary ) ,
197190 detail : messageText ( msg . detail ) ,
198191 } ,
199192 }
200193 console . error ( JSON . stringify ( error , null , 2 ) )
201194 }
202195
203- exit ( typeof er . errno === 'number' ? er . errno : typeof er . code === 'number' ? er . code : 1 )
196+ exit ( typeof err . errno === 'number' ? err . errno : typeof err . code === 'number' ? err . code : 1 )
204197}
205198
206199const messageText = msg => msg . map ( line => line . slice ( 1 ) . join ( ' ' ) ) . join ( '\n' )
@@ -209,8 +202,6 @@ const writeLogFile = () => {
209202 if ( wroteLogFile )
210203 return
211204
212- const os = require ( 'os' )
213-
214205 try {
215206 let logOutput = ''
216207 log . record . forEach ( m => {
@@ -243,8 +234,7 @@ const writeLogFile = () => {
243234 }
244235}
245236
246- module . exports = errorHandler
247- module . exports . exit = exit
237+ module . exports = exitHandler
248238module . exports . setNpm = ( n ) => {
249239 npm = n
250240}
0 commit comments