@@ -5,6 +5,7 @@ import * as path from "path";
5
5
import * as iOSCore from "./ios-core" ;
6
6
import * as helpers from "../../helpers" ;
7
7
import * as plistlib from "plistlib" ;
8
+ import Future = require( "fibers/future" ) ;
8
9
9
10
export class MobileServices {
10
11
public static APPLE_FILE_CONNECTION : string = "com.apple.afc" ;
@@ -161,6 +162,7 @@ export class AfcClient implements Mobile.IAfcClient {
161
162
162
163
public transfer ( localFilePath : string , devicePath : string ) : IFuture < void > {
163
164
return ( ( ) => {
165
+ let future = new Future < void > ( ) ;
164
166
this . ensureDevicePathExist ( path . dirname ( devicePath ) ) ;
165
167
let reader = this . $fs . createReadStream ( localFilePath ) ;
166
168
devicePath = helpers . fromWindowsRelativePathToUnix ( devicePath ) ;
@@ -169,19 +171,44 @@ export class AfcClient implements Mobile.IAfcClient {
169
171
170
172
let target = this . open ( devicePath , "w" ) ;
171
173
let localFilePathSize = this . $fs . getFileSize ( localFilePath ) . wait ( ) ;
174
+ let isErrorCode21Raised = false ,
175
+ futureThrow = ( err : Error ) => {
176
+ if ( ! future . isResolved ( ) ) {
177
+ future . throw ( err ) ;
178
+ }
179
+ } ;
172
180
173
181
reader . on ( "data" , ( data : NodeBuffer ) => {
174
- target . write ( data , data . length ) ;
175
- this . $logger . trace ( "transfer-> localFilePath: '%s', devicePath: '%s', localFilePathSize: '%s', transferred bytes: '%s'" ,
176
- localFilePath , devicePath , localFilePathSize . toString ( ) , data . length . toString ( ) ) ;
177
- } )
178
- . on ( "error" , ( error : Error ) => {
179
- this . $errors . fail ( error ) ;
180
- } )
181
- . on ( "end" , ( ) => target . close ( ) ) ;
182
+ try {
183
+ target . write ( data , data . length ) ;
184
+ this . $logger . trace ( "transfer-> localFilePath: '%s', devicePath: '%s', localFilePathSize: '%s', transferred bytes: '%s'" ,
185
+ localFilePath , devicePath , localFilePathSize . toString ( ) , data . length . toString ( ) ) ;
186
+ } catch ( err ) {
187
+ if ( err . message . indexOf ( "Result is: '21'" ) !== - 1 && ! isErrorCode21Raised ) {
188
+ // Error code 21 is kAFCInterruptedError. It looks like in most cases it is raised on the first package that we try to transfer.
189
+ // However ignoring this error on the first package, does not prevent the application from installing and working correctly.
190
+ // So ignore the first occurrence of the error only.
191
+ this . $logger . warn ( err . message ) ;
192
+ isErrorCode21Raised = true ;
193
+ } else {
194
+ futureThrow ( err ) ;
195
+ }
196
+ }
197
+ } ) ;
198
+
199
+ reader . on ( "error" , ( error : Error ) => {
200
+ futureThrow ( error ) ;
201
+ } ) ;
182
202
183
- this . $fs . futureFromEvent ( reader , "close" ) . wait ( ) ;
203
+ reader . on ( "end" , ( ) => target . close ( ) ) ;
204
+
205
+ reader . on ( "close" , ( ) => {
206
+ if ( ! future . isResolved ( ) ) {
207
+ future . return ( ) ;
208
+ }
209
+ } ) ;
184
210
211
+ future . wait ( ) ;
185
212
} ) . future < void > ( ) ( ) ;
186
213
}
187
214
0 commit comments