1
- let npm // set by the cli
2
- let cbCalled = false
3
1
const log = require ( 'npmlog' )
4
- let itWorked = false
2
+ const os = require ( 'os' )
5
3
const path = require ( 'path' )
6
4
const writeFileAtomic = require ( 'write-file-atomic' )
7
5
const mkdirp = require ( 'mkdirp-infer-owner' )
8
6
const fs = require ( 'graceful-fs' )
9
- let wroteLogFile = false
10
- let exitCode = 0
7
+
11
8
const errorMessage = require ( './error-message.js' )
12
9
const replaceInfo = require ( './replace-info.js' )
13
10
11
+ let exitHandlerCalled = false
14
12
let logFileName
13
+ let npm // set by the cli
14
+ let wroteLogFile = false
15
+
16
+ const timings = { }
17
+
15
18
const getLogFile = ( ) => {
16
19
// we call this multiple times, so we need to treat it as a singleton because
17
20
// the date is part of the name
@@ -21,7 +24,6 @@ const getLogFile = () => {
21
24
return logFileName
22
25
}
23
26
24
- const timings = { }
25
27
process . on ( 'timing' , ( name , value ) => {
26
28
if ( timings [ name ] )
27
29
timings [ name ] += value
@@ -53,22 +55,20 @@ process.on('exit', code => {
53
55
}
54
56
}
55
57
56
- if ( code )
57
- itWorked = false
58
- if ( itWorked )
58
+ if ( ! code )
59
59
log . info ( 'ok' )
60
60
else {
61
- if ( ! cbCalled ) {
62
- log . error ( '' , 'cb() never called!' )
61
+ if ( ! exitHandlerCalled ) {
62
+ log . error ( '' , 'Exit handler never called!' )
63
63
console . error ( '' )
64
64
log . error ( '' , 'This is an error with npm itself. Please report this error at:' )
65
65
log . error ( '' , ' <https://github.com/npm/cli/issues>' )
66
+ // TODO this doesn't have an npm.config.loaded guard
66
67
writeLogFile ( )
67
68
}
68
-
69
- if ( code )
70
- log . verbose ( 'code' , code )
69
+ log . verbose ( 'code' , code )
71
70
}
71
+ // In timing mode we always write the log file
72
72
if ( npm . config && npm . config . loaded && npm . config . get ( 'timing' ) && ! wroteLogFile )
73
73
writeLogFile ( )
74
74
if ( wroteLogFile ) {
@@ -83,52 +83,46 @@ process.on('exit', code => {
83
83
' ' + getLogFile ( ) ,
84
84
] . join ( '\n' )
85
85
)
86
- wroteLogFile = false
87
86
}
88
87
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
92
91
93
- if ( exitCode !== 0 )
94
- process . exit ( exitCode )
92
+ // actually exit.
93
+ process . exit ( code )
95
94
} )
96
95
97
96
const exit = ( code , noLog ) => {
98
- exitCode = exitCode || process . exitCode || code
99
-
100
- log . verbose ( 'exit' , code )
97
+ log . verbose ( 'exit' , code || 0 )
101
98
if ( log . level === 'silent' )
102
99
noLog = true
103
100
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
117
103
if ( code && ! noLog )
118
104
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
+ } )
120
114
}
121
115
122
- const errorHandler = ( er ) => {
116
+ const exitHandler = ( err ) => {
123
117
log . disableProgress ( )
124
118
if ( ! npm . config || ! npm . config . loaded ) {
125
119
// 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 )
128
122
}
129
123
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.' )
132
126
133
127
// only show the notification if it finished before the other stuff we
134
128
// were doing. no need to hang on `npm -v` or something.
@@ -139,68 +133,67 @@ const errorHandler = (er) => {
139
133
log . level = level
140
134
}
141
135
142
- cbCalled = true
143
- if ( ! er )
144
- return exit ( 0 )
136
+ exitHandlerCalled = true
137
+ if ( ! err )
138
+ return exit ( )
145
139
146
140
// if we got a command that just shells out to something else, then it
147
141
// will presumably print its own errors and exit with a proper status
148
142
// code if there's a problem. If we got an error with a code=0, then...
149
143
// something else went wrong along the way, so maybe an npm problem?
150
144
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
152
146
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 )
156
150
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 )
159
153
return exit ( 1 , true )
160
154
}
161
155
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 ]
165
159
}
166
160
167
161
for ( const k of [ 'type' , 'stack' , 'statusCode' , 'pkgid' ] ) {
168
- const v = er [ k ]
162
+ const v = err [ k ]
169
163
if ( v )
170
164
log . verbose ( k , replaceInfo ( v ) )
171
165
}
172
166
173
167
log . verbose ( 'cwd' , process . cwd ( ) )
174
168
175
- const os = require ( 'os' )
176
169
const args = replaceInfo ( process . argv )
177
170
log . verbose ( '' , os . type ( ) + ' ' + os . release ( ) )
178
171
log . verbose ( 'argv' , args . map ( JSON . stringify ) . join ( ' ' ) )
179
172
log . verbose ( 'node' , process . version )
180
173
log . verbose ( 'npm ' , 'v' + npm . version )
181
174
182
175
for ( const k of [ 'code' , 'syscall' , 'file' , 'path' , 'dest' , 'errno' ] ) {
183
- const v = er [ k ]
176
+ const v = err [ k ]
184
177
if ( v )
185
178
log . error ( k , v )
186
179
}
187
180
188
- const msg = errorMessage ( er , npm )
181
+ const msg = errorMessage ( err , npm )
189
182
for ( const errline of [ ...msg . summary , ...msg . detail ] )
190
183
log . error ( ...errline )
191
184
192
185
if ( npm . config && npm . config . get ( 'json' ) ) {
193
186
const error = {
194
187
error : {
195
- code : er . code ,
188
+ code : err . code ,
196
189
summary : messageText ( msg . summary ) ,
197
190
detail : messageText ( msg . detail ) ,
198
191
} ,
199
192
}
200
193
console . error ( JSON . stringify ( error , null , 2 ) )
201
194
}
202
195
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 )
204
197
}
205
198
206
199
const messageText = msg => msg . map ( line => line . slice ( 1 ) . join ( ' ' ) ) . join ( '\n' )
@@ -209,8 +202,6 @@ const writeLogFile = () => {
209
202
if ( wroteLogFile )
210
203
return
211
204
212
- const os = require ( 'os' )
213
-
214
205
try {
215
206
let logOutput = ''
216
207
log . record . forEach ( m => {
@@ -243,8 +234,7 @@ const writeLogFile = () => {
243
234
}
244
235
}
245
236
246
- module . exports = errorHandler
247
- module . exports . exit = exit
237
+ module . exports = exitHandler
248
238
module . exports . setNpm = ( n ) => {
249
239
npm = n
250
240
}
0 commit comments