Skip to content

Commit fcda3e7

Browse files
Fix LiveSync on iOS when app is uninstalled manually
Whenever application is reinstalled on iOS device, we have to execute full sync operation due to iOS runtime requirements. However, in case the application is uninstalled manually during LiveSync, CLI will reinstall it, but the code that checks if a full sync is required will return false. The problem is that the `isRebuilt` property (renamed to `isReinstalled` now) really checks if the application has been rebuild during current check and expectedly this returns false. In order to fix this, change the return type of `ensureLatestAppPackageIsInstalledOnDevice`, so it will give the required information if a full sync should be executed. Also improve the information that we emit in liveSyncExecuted event: * add new property - `isFullSync` - it can be used to indicate the current operation * ensure the `syncedFiles` property contains the really synced files - for Android devices the full sync is not always a full sync - it checks the shasums of files and uploads only the modified ones. At the moment we've been returning all project files in the array, even when we upload only a few (or event none) of them. In order to fix this respect the return type of the `transferDirectory` method and use it in LiveSync operations.
1 parent 28232f3 commit fcda3e7

File tree

6 files changed

+34
-15
lines changed

6 files changed

+34
-15
lines changed

PublicAPI.md

+1
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ tns.liveSyncService.on("liveSyncStarted", data => {
635635
* Full paths to files synced during the operation. In case the `syncedFiles.length` is 0, the operation is "fullSync" (i.e. all project files are synced).
636636
*/
637637
syncedFiles: string[];
638+
isFullSync: boolean;
638639
}
639640
```
640641

lib/definitions/livesync.d.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,16 @@ interface IEnsureLatestAppPackageIsInstalledOnDeviceOptions {
149149
modifiedFiles?: string[];
150150
}
151151

152+
/**
153+
* Describes the action that has been executed during ensureLatestAppPackageIsInstalledOnDevice execution.
154+
*/
155+
interface IAppInstalledOnDeviceResult {
156+
/**
157+
* Defines if the app has been installed on device from the ensureLatestAppPackageIsInstalledOnDevice method.
158+
*/
159+
appInstalled: boolean;
160+
}
161+
152162
/**
153163
* Describes LiveSync operations.
154164
*/
@@ -187,7 +197,7 @@ interface ILiveSyncWatchInfo {
187197
projectData: IProjectData;
188198
filesToRemove: string[];
189199
filesToSync: string[];
190-
isRebuilt: boolean;
200+
isReinstalled: boolean;
191201
syncAllFiles: boolean;
192202
useLiveEdit?: boolean;
193203
}

lib/services/livesync/ios-livesync-service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export class IOSLiveSyncService extends PlatformLiveSyncServiceBase implements I
5959
}
6060

6161
public liveSyncWatchAction(device: Mobile.IDevice, liveSyncInfo: ILiveSyncWatchInfo): Promise<ILiveSyncResultInfo> {
62-
if (liveSyncInfo.isRebuilt) {
62+
if (liveSyncInfo.isReinstalled) {
6363
// In this case we should execute fullsync because iOS Runtime requires the full content of app dir to be extracted in the root of sync dir.
6464
return this.fullSync({ projectData: liveSyncInfo.projectData, device, syncAllFiles: liveSyncInfo.syncAllFiles, watch: true });
6565
} else {

lib/services/livesync/livesync-service.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ export class LiveSyncService extends EventEmitter implements ILiveSyncService {
109109
projectDir: projectData.projectDir,
110110
applicationIdentifier: projectData.projectId,
111111
syncedFiles: liveSyncResultInfo.modifiedFilesData.map(m => m.getLocalPath()),
112-
deviceIdentifier: liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier
112+
deviceIdentifier: liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier,
113+
isFullSync: liveSyncResultInfo.isFullSync
113114
});
114115

115116
this.$logger.info(`Successfully synced application ${liveSyncResultInfo.deviceAppData.appIdentifier} on device ${liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier}.`);
@@ -154,8 +155,9 @@ export class LiveSyncService extends EventEmitter implements ILiveSyncService {
154155
throw new Error(`Invalid platform ${platform}. Supported platforms are: ${this.$mobileHelper.platformNames.join(", ")}`);
155156
}
156157

157-
private async ensureLatestAppPackageIsInstalledOnDevice(options: IEnsureLatestAppPackageIsInstalledOnDeviceOptions, nativePrepare?: INativePrepare): Promise<void> {
158+
private async ensureLatestAppPackageIsInstalledOnDevice(options: IEnsureLatestAppPackageIsInstalledOnDeviceOptions, nativePrepare?: INativePrepare): Promise<IAppInstalledOnDeviceResult> {
158159
const platform = options.device.deviceInfo.platform;
160+
const appInstalledOnDeviceResult: IAppInstalledOnDeviceResult = { appInstalled: false };
159161
if (options.preparedPlatforms.indexOf(platform) === -1) {
160162
options.preparedPlatforms.push(platform);
161163
// TODO: Pass provision and sdk as a fifth argument here
@@ -167,7 +169,8 @@ export class LiveSyncService extends EventEmitter implements ILiveSyncService {
167169

168170
const buildResult = await this.installedCachedAppPackage(platform, options);
169171
if (buildResult) {
170-
return;
172+
appInstalledOnDeviceResult.appInstalled = true;
173+
return appInstalledOnDeviceResult;
171174
}
172175

173176
// TODO: Pass provision and sdk as a fifth argument here
@@ -176,7 +179,6 @@ export class LiveSyncService extends EventEmitter implements ILiveSyncService {
176179
let action = LiveSyncTrackActionNames.LIVESYNC_OPERATION;
177180
if (shouldBuild) {
178181
pathToBuildItem = await options.deviceBuildInfoDescriptor.buildAction();
179-
// Is it possible to return shouldBuild for two devices? What about android device and android emulator?
180182
options.rebuiltInformation.push({ isEmulator: options.device.isEmulator, platform, pathToBuildItem });
181183
action = LiveSyncTrackActionNames.LIVESYNC_OPERATION_BUILD;
182184
}
@@ -186,7 +188,10 @@ export class LiveSyncService extends EventEmitter implements ILiveSyncService {
186188
const shouldInstall = await this.$platformService.shouldInstall(options.device, options.projectData, options.deviceBuildInfoDescriptor.outputPath);
187189
if (shouldInstall) {
188190
await this.$platformService.installApplication(options.device, { release: false }, options.projectData, pathToBuildItem, options.deviceBuildInfoDescriptor.outputPath);
191+
appInstalledOnDeviceResult.appInstalled = true;
189192
}
193+
194+
return appInstalledOnDeviceResult;
190195
}
191196

192197
private async trackAction(action: string, platform: string, options: IEnsureLatestAppPackageIsInstalledOnDeviceOptions): Promise<void> {
@@ -331,7 +336,7 @@ export class LiveSyncService extends EventEmitter implements ILiveSyncService {
331336
const liveSyncProcessInfo = this.liveSyncProcessesInfo[projectData.projectDir];
332337
const deviceBuildInfoDescriptor = _.find(liveSyncProcessInfo.deviceDescriptors, dd => dd.identifier === device.deviceInfo.identifier);
333338

334-
await this.ensureLatestAppPackageIsInstalledOnDevice({
339+
const appInstalledOnDeviceResult = await this.ensureLatestAppPackageIsInstalledOnDevice({
335340
device,
336341
preparedPlatforms,
337342
rebuiltInformation,
@@ -346,7 +351,7 @@ export class LiveSyncService extends EventEmitter implements ILiveSyncService {
346351
projectData,
347352
filesToRemove: currentFilesToRemove,
348353
filesToSync: currentFilesToSync,
349-
isRebuilt: !!_.find(rebuiltInformation, info => info.isEmulator === device.isEmulator && info.platform === device.deviceInfo.platform),
354+
isReinstalled: appInstalledOnDeviceResult.appInstalled,
350355
syncAllFiles: liveSyncData.watchAllFiles,
351356
useLiveEdit: liveSyncData.useLiveEdit
352357
};

lib/services/livesync/platform-livesync-service-base.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ export abstract class PlatformLiveSyncServiceBase {
4444

4545
const projectFilesPath = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME);
4646
const localToDevicePaths = await this.$projectFilesManager.createLocalToDevicePaths(deviceAppData, projectFilesPath, null, []);
47-
await this.transferFiles(deviceAppData, localToDevicePaths, projectFilesPath, true);
47+
const modifiedFilesData = await this.transferFiles(deviceAppData, localToDevicePaths, projectFilesPath, true);
4848

4949
return {
50-
modifiedFilesData: localToDevicePaths,
50+
modifiedFilesData,
5151
isFullSync: true,
5252
deviceAppData
5353
};
@@ -96,19 +96,22 @@ export abstract class PlatformLiveSyncServiceBase {
9696

9797
return {
9898
modifiedFilesData: modifiedLocalToDevicePaths,
99-
isFullSync: liveSyncInfo.isRebuilt,
99+
isFullSync: liveSyncInfo.isReinstalled,
100100
deviceAppData
101101
};
102102
}
103103

104-
protected async transferFiles(deviceAppData: Mobile.IDeviceAppData, localToDevicePaths: Mobile.ILocalToDevicePathData[], projectFilesPath: string, isFullSync: boolean): Promise<void> {
104+
protected async transferFiles(deviceAppData: Mobile.IDeviceAppData, localToDevicePaths: Mobile.ILocalToDevicePathData[], projectFilesPath: string, isFullSync: boolean): Promise<Mobile.ILocalToDevicePathData[]> {
105+
let transferredFiles = localToDevicePaths;
105106
if (isFullSync) {
106-
await deviceAppData.device.fileSystem.transferDirectory(deviceAppData, localToDevicePaths, projectFilesPath);
107+
transferredFiles = await deviceAppData.device.fileSystem.transferDirectory(deviceAppData, localToDevicePaths, projectFilesPath);
107108
} else {
108109
await deviceAppData.device.fileSystem.transferFiles(deviceAppData, localToDevicePaths);
109110
}
110111

111-
this.logFilesSyncInformation(localToDevicePaths, "Successfully transferred %s.", this.$logger.info);
112+
this.logFilesSyncInformation(transferredFiles, "Successfully transferred %s.", this.$logger.info);
113+
114+
return transferredFiles;
112115
}
113116

114117
protected async getAppData(syncInfo: IFullSyncInfo): Promise<Mobile.IDeviceAppData> {

0 commit comments

Comments
 (0)