Skip to content

Commit 11221ae

Browse files
Fatme Havaluovarosen-vladimirov
authored andcommitted
Speed up livesync on android device by using hash file
Optimize the usage of `tns livesync android` command. In case your project is huge, every time you use it, the full project will be transferred to device. Persist all file hashes of project's files and next time when command is executed transfer only the changed ones. The json which contains hashes information should be on device, so when the device is attached to another PC, where the same project is developed, we'll still transfer only the changed files. Related: #921
1 parent d039e62 commit 11221ae

File tree

7 files changed

+61
-9
lines changed

7 files changed

+61
-9
lines changed

lib/definitions/platform.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ interface IPlatformService {
88
runPlatform(platform: string, buildConfig?: IBuildConfig): IFuture<void>;
99
preparePlatform(platform: string): IFuture<boolean>;
1010
buildPlatform(platform: string, buildConfig?: IBuildConfig): IFuture<void>;
11+
buildForDeploy(platform: string, buildConfig?: IBuildConfig): IFuture<void>;
1112
installOnDevice(platform: string, buildConfig?: IBuildConfig): IFuture<void>;
1213
deployOnDevice(platform: string, buildConfig?: IBuildConfig): IFuture<void>;
1314
deployOnEmulator(platform: string, buildConfig?: IBuildConfig): IFuture<void>;

lib/providers/device-app-data-provider.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
import * as deviceAppDataBaseLib from "../common/mobile/device-app-data/device-app-data-base";
44
import Future = require("fibers/future");
55
import * as path from "path";
6+
import {AndroidDeviceHashService} from "../common/mobile/android/android-device-hash-service";
7+
import {AndroidDebugBridge} from "../common/mobile/android/android-debug-bridge";
8+
9+
const SYNC_DIR_NAME = "sync";
10+
const FULLSYNC_DIR_NAME = "fullsync";
611

712
export class IOSAppIdentifier extends deviceAppDataBaseLib.DeviceAppDataBase implements Mobile.IDeviceAppData {
813
private static DEVICE_PROJECT_ROOT_PATH = "Library/Application Support/LiveSync/app";
@@ -37,18 +42,34 @@ export class AndroidAppIdentifier extends deviceAppDataBaseLib.DeviceAppDataBase
3742
constructor(_appIdentifier: string,
3843
public device: Mobile.IDevice,
3944
public platform: string,
40-
private $options: IOptions) {
45+
private $options: IOptions,
46+
private $injector: IInjector) {
4147
super(_appIdentifier);
4248
}
4349

50+
private _deviceProjectRootPath: string;
51+
4452
public get deviceProjectRootPath(): string {
45-
let syncFolderName = this.$options.watch ? "sync" : "fullsync";
46-
return `/data/local/tmp/${this.appIdentifier}/${syncFolderName}`;
53+
if(!this._deviceProjectRootPath) {
54+
let syncFolderName = this.getSyncFolderName().wait();
55+
this._deviceProjectRootPath = `/data/local/tmp/${this.appIdentifier}/${syncFolderName}`;
56+
}
57+
58+
return this._deviceProjectRootPath;
4759
}
4860

4961
public isLiveSyncSupported(): IFuture<boolean> {
5062
return Future.fromResult(true);
5163
}
64+
65+
private getSyncFolderName(): IFuture<string> {
66+
return ((): string =>{
67+
let adb = this.$injector.resolve(AndroidDebugBridge, { identifier: this.device.deviceInfo.identifier });
68+
let deviceHashService = this.$injector.resolve(AndroidDeviceHashService, {adb: adb, appIdentifier: this.appIdentifier});
69+
let hashFile = this.$options.force ? null : deviceHashService.doesShasumFileExistsOnDevice().wait();
70+
return this.$options.watch || hashFile ? SYNC_DIR_NAME : FULLSYNC_DIR_NAME;
71+
}).future<string>()();
72+
}
5273
}
5374

5475
export class DeviceAppDataProvider implements Mobile.IDeviceAppDataProvider {

lib/providers/livesync-provider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export class LiveSyncProvider implements ILiveSyncProvider {
2525

2626
public buildForDevice(device: Mobile.IDevice): IFuture<string> {
2727
return (() => {
28-
this.$platformService.buildPlatform(device.deviceInfo.platform, {buildForDevice: !device.isEmulator}).wait();
28+
this.$platformService.buildForDeploy(device.deviceInfo.platform, {buildForDevice: !device.isEmulator}).wait();
2929
let platformData = this.$platformsData.getPlatformData(device.deviceInfo.platform);
3030
if (device.isEmulator) {
3131
return this.$platformService.getLatestApplicationPackageForEmulator(platformData).wait().packageName;

lib/services/android-project-service.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as constants from "../constants";
77
import * as semver from "semver";
88
import * as projectServiceBaseLib from "./platform-project-service-base";
99
import * as androidDebugBridgePath from "../common/mobile/android/android-debug-bridge";
10+
import {AndroidDeviceHashService} from "../common/mobile/android/android-device-hash-service";
1011

1112
export class AndroidProjectService extends projectServiceBaseLib.PlatformProjectServiceBase implements IPlatformProjectService {
1213
private static VALUES_DIRNAME = "values";
@@ -29,7 +30,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
2930
private $sysInfo: ISysInfo,
3031
private $mobileHelper: Mobile.IMobileHelper,
3132
private $injector: IInjector,
32-
private $pluginVariablesService: IPluginVariablesService) {
33+
private $pluginVariablesService: IPluginVariablesService,
34+
private $deviceAppDataFactory: Mobile.IDeviceAppDataFactory) {
3335
super($fs, $projectData, $projectDataService);
3436
this._androidProjectPropertiesManagers = Object.create(null);
3537
}
@@ -330,6 +332,14 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
330332
adb.executeShellCommand(["rm", "-rf", this.$mobileHelper.buildDevicePath(deviceRootPath, "fullsync"),
331333
this.$mobileHelper.buildDevicePath(deviceRootPath, "sync"),
332334
this.$mobileHelper.buildDevicePath(deviceRootPath, "removedsync")]).wait();
335+
336+
let projectFilesManager = this.$injector.resolve("projectFilesManager"); // We need to resolve projectFilesManager here due to cyclic dependency
337+
let devicesService: Mobile.IDevicesService = this.$injector.resolve("devicesService");
338+
let device = _.find(devicesService.getDevicesForPlatform(this.platformData.normalizedPlatformName), d => d.deviceInfo.identifier === deviceIdentifier);
339+
let deviceAppData = this.$deviceAppDataFactory.create(this.$projectData.projectId, this.platformData.normalizedPlatformName, device);
340+
let localToDevicePaths = projectFilesManager.createLocalToDevicePaths(deviceAppData, path.join(this.platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME));
341+
let deviceHashService = this.$injector.resolve(AndroidDeviceHashService, { adb: adb, appIdentifier: this.$projectData.projectId });
342+
deviceHashService.uploadHashFileToDevice(localToDevicePaths).wait();
333343
}).future<void>()();
334344
}
335345

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
///<reference path="../../.d.ts"/>
22
"use strict";
33

4+
import {AndroidDebugBridge} from "../../common/mobile/android/android-debug-bridge";
5+
import {AndroidDeviceHashService} from "../../common/mobile/android/android-device-hash-service";
46
import Future = require("fibers/future");
57
import * as helpers from "../../common/helpers";
68
import liveSyncServiceBaseLib = require("./livesync-service-base");
@@ -13,7 +15,9 @@ class AndroidLiveSyncService extends liveSyncServiceBaseLib.LiveSyncServiceBase<
1315
constructor(_device: Mobile.IDevice,
1416
private $fs: IFileSystem,
1517
private $mobileHelper: Mobile.IMobileHelper,
16-
private $options: IOptions) {
18+
private $options: IOptions,
19+
private $injector: IInjector,
20+
private $projectData: IProjectData) {
1721
super(_device);
1822
}
1923

@@ -53,9 +57,15 @@ class AndroidLiveSyncService extends liveSyncServiceBaseLib.LiveSyncServiceBase<
5357
let deviceFilePath = this.$mobileHelper.buildDevicePath(deviceRootPath, "removedsync", relativeUnixPath);
5458
this.device.adb.executeShellCommand(["mkdir", "-p", path.dirname(deviceFilePath), "&&", "touch", deviceFilePath]).wait();
5559
});
60+
61+
this.deviceHashService.removeHashes(localToDevicePaths).wait();
5662
}).future<void>()();
5763
}
5864

65+
public afterInstallApplicationAction(deviceAppData: Mobile.IDeviceAppData, localToDevicePaths: Mobile.ILocalToDevicePathData[]): IFuture<void> {
66+
return this.deviceHashService.uploadHashFileToDevice(localToDevicePaths);
67+
}
68+
5969
private getDeviceRootPath(appIdentifier: string): string {
6070
return `/data/local/tmp/${appIdentifier}`;
6171
}
@@ -77,5 +87,15 @@ class AndroidLiveSyncService extends liveSyncServiceBaseLib.LiveSyncServiceBase<
7787

7888
return future;
7989
}
90+
91+
private _deviceHashService: Mobile.IAndroidDeviceHashService;
92+
private get deviceHashService(): Mobile.IAndroidDeviceHashService {
93+
if (!this._deviceHashService) {
94+
let adb = this.$injector.resolve(AndroidDebugBridge, { identifier: this.device.deviceInfo.identifier });
95+
this._deviceHashService = this.$injector.resolve(AndroidDeviceHashService, { adb: adb, appIdentifier: this.$projectData.projectId });
96+
}
97+
98+
return this._deviceHashService;
99+
}
80100
}
81101
$injector.register("androidLiveSyncServiceLocator", {factory: AndroidLiveSyncService});

lib/services/platform-service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ export class PlatformService implements IPlatformService {
311311
}).future<void>()();
312312
}
313313

314-
public buildForDeploy(platform: string, buildConfig?: IBuildConfig): IFuture<string> {
314+
public buildForDeploy(platform: string, buildConfig?: IBuildConfig): IFuture<void> {
315315
return (() => {
316316
platform = platform.toLowerCase();
317317
if (!this.preparePlatform(platform).wait()) {
@@ -321,7 +321,7 @@ export class PlatformService implements IPlatformService {
321321
let platformData = this.$platformsData.getPlatformData(platform);
322322
platformData.platformProjectService.buildForDeploy(platformData.projectRoot, buildConfig).wait();
323323
this.$logger.out("Project successfully built");
324-
}).future<string>()();
324+
}).future<void>()();
325325
}
326326

327327
public copyLastOutput(platform: string, targetPath: string, settings: {isForDevice: boolean}): IFuture<void> {

0 commit comments

Comments
 (0)