@@ -24,11 +24,28 @@ const buildSocketPath = () => tmp.dir()
24
24
return path . join ( prefix , cleanedPath , 'echo.sock' ) ;
25
25
} ) ;
26
26
27
+ /**
28
+ * Flow type definition:
29
+ *
30
+ * type BuildCredentialsCallbackProcess =
31
+ * (
32
+ * spawnedProcess: ChildProcess,
33
+ * callback: (
34
+ * passwordOnly: boolean,
35
+ * callback: (usernamePrompt: boolean) =>
36
+ * (username: string, password: ?string, cancel: boolean) =>
37
+ * void
38
+ * )
39
+ * ),
40
+ * reject: Error => Promise<void>
41
+ * ) =>
42
+ * (chunk: Buffer) =>
43
+ * string;
44
+ */
27
45
const buildCredentialsCallbackProcess = ( spawnedProcess , callback , reject ) => {
28
46
let credentials = { } ;
29
47
const credentialsCallback = needsUsername => ( username , password , cancel ) => {
30
48
if ( cancel ) {
31
- // we are done here
32
49
spawnedProcess . destroy ( ) ;
33
50
return reject ( new Error ( 'LFS action cancelled' ) ) ;
34
51
}
@@ -42,22 +59,23 @@ const buildCredentialsCallbackProcess = (spawnedProcess, callback, reject) => {
42
59
const output = chunk . toString ( ) ;
43
60
44
61
if ( output . match ( regex . USERNAME ) ) {
62
+ // We're caching the username in-memory in case the process asks for the username several
63
+ // times (for example, LFS re-prompts for credentials on every file).
45
64
if ( credentials . username ) {
46
65
spawnedProcess . write ( credentials . username ) ;
47
66
spawnedProcess . write ( EOL ) ;
48
67
} else {
49
- // If we have a username we need to make sure to prompt for it
50
68
callback ( true , credentialsCallback ( true ) ) ;
51
69
}
52
70
} else if ( output . match ( regex . PASSWORD ) ) {
53
71
if ( credentials . password ) {
54
72
spawnedProcess . write ( credentials . password ) ;
55
73
spawnedProcess . write ( EOL ) ;
56
74
} else {
57
- // no username so maybe ssh?
58
75
callback ( false , credentialsCallback ( false ) ) ;
59
76
}
60
77
}
78
+
61
79
return output ;
62
80
} ;
63
81
} ;
@@ -69,8 +87,7 @@ const buildSocket = (size, closeProcess, socketName, mainResolve, mainReject) =>
69
87
let resolved = false ;
70
88
71
89
const closedOrEnded = ( ) => {
72
- // For some reason this fires twice so after
73
- // the first fire let's move on
90
+ // Don't fire this callback if it's already been called.
74
91
if ( ! resolved ) {
75
92
mainResolve ( { stdout : Buffer . concat ( bufferList ) } ) ;
76
93
resolved = true ;
@@ -90,6 +107,7 @@ const buildSocket = (size, closeProcess, socketName, mainResolve, mainReject) =>
90
107
} ) ;
91
108
socket . on ( 'error' , mainReject ) ;
92
109
} ) ;
110
+
93
111
socketServer . listen ( socketName ) ;
94
112
socketServer . on ( 'listening' , ( ) => {
95
113
resolve ( socketName ) ;
@@ -200,3 +218,9 @@ const spawn = (command, opts = {}, callback) => new Promise(
200
218
} ) ;
201
219
202
220
export default spawn ;
221
+
222
+ export const __TESTING__ = { // eslint-disable-line no-underscore-dangle
223
+ buildCredentialsCallbackProcess,
224
+ buildSocket,
225
+ buildSocketPath
226
+ } ;
0 commit comments