Skip to content

Commit

Permalink
chore: merge branch 'release' into vladimirov/merge-rel-master
Browse files Browse the repository at this point in the history
  • Loading branch information
rosen-vladimirov committed Aug 4, 2018
2 parents 242b03f + 4db0a8e commit be31335
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 43 deletions.
1 change: 1 addition & 0 deletions lib/constants.ts
Expand Up @@ -54,6 +54,7 @@ export class LiveSyncTrackActionNames {
}

export const PackageJsonKeysToKeep: Array<String> = ["name", "main", "android", "version", "pluginsData"];
export const TemplatesV2PackageJsonKeysToRemove: Array<String> = ["name", "version", "displayName", "templateType", "author", "keywords", "homepage", "bugs"];

export class SaveOptions {
static PRODUCTION = "save";
Expand Down
4 changes: 2 additions & 2 deletions lib/definitions/livesync-global.d.ts
@@ -1,7 +1,7 @@
import * as stream from "stream";
import { Socket } from "net";

declare global {
interface IDuplexSocket extends stream.Duplex {
interface INetSocket extends Socket {
uid?: string;
}
}
Expand Down
18 changes: 10 additions & 8 deletions lib/definitions/livesync.d.ts
Expand Up @@ -332,6 +332,8 @@ interface ILiveSyncResultInfo {
useLiveEdit?: boolean;
}

interface IAndroidLiveSyncResultInfo extends ILiveSyncResultInfo, IAndroidLivesyncSyncOperationResult { }

interface IFullSyncInfo extends IProjectDataComposition {
device: Mobile.IDevice;
watch: boolean;
Expand Down Expand Up @@ -377,22 +379,22 @@ interface INativeScriptDeviceLiveSyncService extends IDeviceLiveSyncServiceBase
* @return {Promise<Mobile.ILocalToDevicePathData[]>} Returns the ILocalToDevicePathData of all transfered files
*/
transferFiles(deviceAppData: Mobile.IDeviceAppData, localToDevicePaths: Mobile.ILocalToDevicePathData[], projectFilesPath: string, isFullSync: boolean): Promise<Mobile.ILocalToDevicePathData[]>;

/**
* Guarantees all remove/update operations have finished
* @param {ILiveSyncResultInfo} liveSyncInfo Describes the LiveSync operation - for which project directory is the operation and other settings.
* @return {Promise<void>}
*/
finalizeSync(liveSyncInfo: ILiveSyncResultInfo): Promise<void>;
}

interface IAndroidNativeScriptDeviceLiveSyncService {
interface IAndroidNativeScriptDeviceLiveSyncService extends INativeScriptDeviceLiveSyncService {
/**
* Retrieves the android device's hash service.
* @param {string} appIdentifier Application identifier.
* @return {Promise<Mobile.IAndroidDeviceHashService>} The hash service
*/
getDeviceHashService(appIdentifier: string): Mobile.IAndroidDeviceHashService;

/**
* Guarantees all remove/update operations have finished
* @param {ILiveSyncResultInfo} liveSyncInfo Describes the LiveSync operation - for which project directory is the operation and other settings.
* @return {Promise<IAndroidLiveSyncResultInfo>}
*/
finalizeSync(liveSyncInfo: ILiveSyncResultInfo, projectData: IProjectData): Promise<IAndroidLivesyncSyncOperationResult>;
}

interface IAndroidLivesyncTool {
Expand Down
44 changes: 27 additions & 17 deletions lib/services/livesync/android-device-livesync-sockets-service.ts
Expand Up @@ -39,18 +39,23 @@ export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBa
return `${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${appIdentifier}-livesync-in-progress`;
}

public async finalizeSync(liveSyncInfo: ILiveSyncResultInfo) {
await this.doSync(liveSyncInfo);
public async finalizeSync(liveSyncInfo: ILiveSyncResultInfo, projectData: IProjectData): Promise<IAndroidLivesyncSyncOperationResult> {
try {
const result = await this.doSync(liveSyncInfo, projectData);
return result;
} finally {
this.livesyncTool.end();
}
}

private async doSync(liveSyncInfo: ILiveSyncResultInfo, { doRefresh = false }: { doRefresh?: boolean } = {}): Promise<IAndroidLivesyncSyncOperationResult> {
private async doSync(liveSyncInfo: ILiveSyncResultInfo, projectData: IProjectData): Promise<IAndroidLivesyncSyncOperationResult> {
const operationId = this.livesyncTool.generateOperationIdentifier();

let result = { operationId, didRefresh: true };

if (liveSyncInfo.modifiedFilesData.length) {

const doSyncPromise = this.livesyncTool.sendDoSyncOperation(doRefresh, null, operationId);
const canExecuteFastSync = !liveSyncInfo.isFullSync && this.canExecuteFastSyncForPaths(liveSyncInfo.modifiedFilesData, projectData, this.device.deviceInfo.platform);
const doSyncPromise = this.livesyncTool.sendDoSyncOperation(canExecuteFastSync, null, operationId);

const syncInterval: NodeJS.Timer = setInterval(() => {
if (this.livesyncTool.isOperationInProgress(operationId)) {
Expand All @@ -64,30 +69,29 @@ export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBa
};

this.$processService.attachToProcessExitSignals(this, actionOnEnd);
doSyncPromise.then(actionOnEnd, actionOnEnd);
// We need to clear resources when the action fails
// But we also need the real result of the action.
await doSyncPromise.then(actionOnEnd.bind(this), actionOnEnd.bind(this));

result = await doSyncPromise;
} else {
await this.device.fileSystem.deleteFile(this.getPathToLiveSyncFileOnDevice(liveSyncInfo.deviceAppData.appIdentifier), liveSyncInfo.deviceAppData.appIdentifier);
}

await this.device.fileSystem.deleteFile(this.getPathToLiveSyncFileOnDevice(liveSyncInfo.deviceAppData.appIdentifier), liveSyncInfo.deviceAppData.appIdentifier);

return result;
}

public async refreshApplication(projectData: IProjectData, liveSyncInfo: ILiveSyncResultInfo) {
public async refreshApplication(projectData: IProjectData, liveSyncInfo: IAndroidLiveSyncResultInfo) {
const canExecuteFastSync = !liveSyncInfo.isFullSync && this.canExecuteFastSyncForPaths(liveSyncInfo.modifiedFilesData, projectData, this.device.deviceInfo.platform);

const syncOperationResult = await this.doSync(liveSyncInfo, { doRefresh: canExecuteFastSync });

this.livesyncTool.end();

if (!canExecuteFastSync || !syncOperationResult.didRefresh) {
if (!canExecuteFastSync || !liveSyncInfo.didRefresh) {
await this.device.applicationManager.restartApplication({ appId: liveSyncInfo.deviceAppData.appIdentifier, projectName: projectData.projectName });
}
}

public async removeFiles(deviceAppData: Mobile.IDeviceAppData, localToDevicePaths: Mobile.ILocalToDevicePathData[], projectFilesPath: string): Promise<void> {
await this.livesyncTool.removeFiles(_.map(localToDevicePaths, (element: any) => element.filePath));

await this.getDeviceHashService(deviceAppData.appIdentifier).removeHashes(localToDevicePaths);
}

public async transferFiles(deviceAppData: Mobile.IDeviceAppData, localToDevicePaths: Mobile.ILocalToDevicePathData[], projectFilesPath: string, isFullSync: boolean): Promise<Mobile.ILocalToDevicePathData[]> {
Expand All @@ -96,15 +100,21 @@ export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBa
if (isFullSync) {
transferredFiles = await this._transferDirectory(deviceAppData, localToDevicePaths, projectFilesPath);
} else {
transferredFiles = await this._transferFiles(localToDevicePaths);
transferredFiles = await this._transferFiles(deviceAppData, localToDevicePaths);
}

return transferredFiles;
}

private async _transferFiles(localToDevicePaths: Mobile.ILocalToDevicePathData[]): Promise<Mobile.ILocalToDevicePathData[]> {
private async _transferFiles(deviceAppData: Mobile.IDeviceAppData, localToDevicePaths: Mobile.ILocalToDevicePathData[]): Promise<Mobile.ILocalToDevicePathData[]> {
await this.livesyncTool.sendFiles(localToDevicePaths.map(localToDevicePathData => localToDevicePathData.getLocalPath()));

// Update hashes
const deviceHashService = this.getDeviceHashService(deviceAppData.appIdentifier);
if (! await deviceHashService.updateHashes(localToDevicePaths)) {
this.$logger.trace("Unable to find hash file on device. The next livesync command will create it.");
}

return localToDevicePaths;
}

Expand Down
19 changes: 19 additions & 0 deletions lib/services/livesync/android-livesync-service.ts
Expand Up @@ -23,6 +23,25 @@ export class AndroidLiveSyncService extends PlatformLiveSyncServiceBase implemen
return this.$injector.resolve<INativeScriptDeviceLiveSyncService>(AndroidDeviceLiveSyncService, { device, data });
}

public async liveSyncWatchAction(device: Mobile.IDevice, liveSyncInfo: ILiveSyncWatchInfo): Promise<IAndroidLiveSyncResultInfo> {
const liveSyncResult = await super.liveSyncWatchAction(device, liveSyncInfo);
const result = await this.finalizeSync(device, liveSyncInfo.projectData, liveSyncResult);
return result;
}

public async fullSync(syncInfo: IFullSyncInfo): Promise<IAndroidLiveSyncResultInfo> {
const liveSyncResult = await super.fullSync(syncInfo);
const result = await this.finalizeSync(syncInfo.device, syncInfo.projectData, liveSyncResult);
return result;
}

public async prepareForLiveSync(device: Mobile.IDevice, data: IProjectDir): Promise<void> { /* */ }

private async finalizeSync(device: Mobile.IDevice, projectData: IProjectData, liveSyncResult: ILiveSyncResultInfo): Promise<IAndroidLiveSyncResultInfo> {
const liveSyncService = <IAndroidNativeScriptDeviceLiveSyncService>this.getDeviceLiveSyncService(device, projectData);
const finalizeResult = await liveSyncService.finalizeSync(liveSyncResult, projectData);
const result = _.extend(liveSyncResult, finalizeResult);
return result;
}
}
$injector.register("androidLiveSyncService", AndroidLiveSyncService);
13 changes: 7 additions & 6 deletions lib/services/livesync/android-livesync-tool.ts
Expand Up @@ -22,13 +22,13 @@ const DEFAULT_LOCAL_HOST_ADDRESS = "127.0.0.1";
export class AndroidLivesyncTool implements IAndroidLivesyncTool {
private operationPromises: IDictionary<any>;
private socketError: string | Error;
private socketConnection: IDuplexSocket;
private socketConnection: INetSocket;
private configuration: IAndroidLivesyncToolConfiguration;
private pendingConnectionData: {
connectionTimer?: NodeJS.Timer,
socketTimer?: NodeJS.Timer,
rejectHandler?: Function,
socket?: IDuplexSocket
socket?: INetSocket
} = null;

constructor(private $androidProcessService: Mobile.IAndroidProcessService,
Expand Down Expand Up @@ -173,6 +173,7 @@ export class AndroidLivesyncTool implements IAndroidLivesyncTool {
this.cleanState(socketUid);
//call end of the connection (close and error callbacks won't be called - listeners removed)
socket.end();
socket.destroy();
//reject all pending sync requests and clear timeouts
this.rejectPendingSyncOperations(socketUid, error);
}
Expand Down Expand Up @@ -254,7 +255,7 @@ export class AndroidLivesyncTool implements IAndroidLivesyncTool {
});
}

private createSocket(port: number): IDuplexSocket {
private createSocket(port: number): INetSocket {
const socket = new net.Socket();
socket.connect(port, this.configuration.localHostAddress);
return socket;
Expand All @@ -280,7 +281,7 @@ export class AndroidLivesyncTool implements IAndroidLivesyncTool {
}
}

private handleConnection({ socket, data }: { socket: IDuplexSocket, data: NodeBuffer | string }) {
private handleConnection({ socket, data }: { socket: INetSocket, data: NodeBuffer | string }) {
this.socketConnection = socket;
this.socketConnection.uid = this.generateOperationIdentifier();

Expand All @@ -304,15 +305,15 @@ export class AndroidLivesyncTool implements IAndroidLivesyncTool {
});
}

private connectEventuallyUntilTimeout(factory: () => IDuplexSocket, timeout: number): Promise<{socket: IDuplexSocket, data: NodeBuffer | string}> {
private connectEventuallyUntilTimeout(factory: () => INetSocket, timeout: number): Promise<{socket: INetSocket, data: NodeBuffer | string}> {
return new Promise((resolve, reject) => {
let lastKnownError: Error | string,
isConnected = false;

const connectionTimer = setTimeout(() => {
if (!isConnected) {
isConnected = true;
reject(lastKnownError || { message: "Socket connection timeouted." });
reject(lastKnownError || new Error("Socket connection timeouted."));
this.pendingConnectionData = null;
}
}, timeout);
Expand Down
6 changes: 5 additions & 1 deletion lib/services/livesync/device-livesync-service-base.ts
Expand Up @@ -39,7 +39,11 @@ export abstract class DeviceLiveSyncServiceBase {
return transferredFiles;
}

public async finalizeSync(liveSyncInfo: ILiveSyncResultInfo): Promise<void> {
public async finalizeSync(liveSyncInfo: ILiveSyncResultInfo, projectData: IProjectData): Promise<IAndroidLivesyncSyncOperationResult> {
//implement in case a sync point for all remove/create operation is needed
return {
didRefresh:true,
operationId: ""
};
}
}
3 changes: 0 additions & 3 deletions lib/services/livesync/livesync-service.ts
Expand Up @@ -164,9 +164,6 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
};

try {
const platformLiveSyncService = this.getLiveSyncService(liveSyncResultInfo.deviceAppData.platform);
const deviceLivesyncService = platformLiveSyncService.getDeviceLiveSyncService(deviceAppData.device, projectData);
await deviceLivesyncService.finalizeSync(liveSyncResultInfo);
await deviceAppData.device.applicationManager.stopApplication({ appId: applicationId, projectName: projectData.projectName });
// Now that we've stopped the application we know it isn't started, so set debugOptions.start to false
// so that it doesn't default to true in attachDebugger method
Expand Down
4 changes: 4 additions & 0 deletions lib/services/pacote-service.ts
Expand Up @@ -29,6 +29,10 @@ export class PacoteService implements IPacoteService {
_.extend(extractOptions, options);
}

if (this.$fs.exists(packageName)) {
packageName = path.resolve(packageName);
}

const cache = await this.$npm.getCachePath();
return new Promise<void>((resolve, reject) => {
const source = pacote.tarball.stream(packageName, { cache });
Expand Down
4 changes: 2 additions & 2 deletions lib/services/project-service.ts
Expand Up @@ -3,7 +3,7 @@ import * as path from "path";
import * as shelljs from "shelljs";
import { format } from "util";
import { exported } from "../common/decorators";
import { Hooks } from "../constants";
import { Hooks, TemplatesV2PackageJsonKeysToRemove } from "../constants";

export class ProjectService implements IProjectService {

Expand Down Expand Up @@ -212,7 +212,7 @@ export class ProjectService implements IProjectService {
const packageJsonData = this.$fs.readJson(projectFilePath);

// Remove the metadata keys from the package.json
let updatedPackageJsonData = _.omitBy<any, any>(packageJsonData, (value: any, key: string) => _.startsWith(key, "_"));
let updatedPackageJsonData = _.omitBy<any, any>(packageJsonData, (value: any, key: string) => _.startsWith(key, "_") || TemplatesV2PackageJsonKeysToRemove.indexOf(key) !== -1);
updatedPackageJsonData = _.merge(updatedPackageJsonData, this.packageJsonDefaultData);

if (updatedPackageJsonData.nativescript && updatedPackageJsonData.nativescript.templateVersion) {
Expand Down
12 changes: 9 additions & 3 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -46,7 +46,7 @@
"ios-sim-portable": "4.0.2",
"jimp": "0.2.28",
"lockfile": "1.0.3",
"lodash": "4.13.1",
"lodash": "4.17.10",
"log4js": "1.0.1",
"marked": "0.3.12",
"marked-terminal": "2.0.0",
Expand Down Expand Up @@ -89,6 +89,7 @@
"@types/chokidar": "1.6.0",
"@types/color": "3.0.0",
"@types/lockfile": "1.0.0",
"@types/lodash": "4.14.116",
"@types/node": "6.0.61",
"@types/ora": "1.3.3",
"@types/qr-image": "3.2.0",
Expand Down

0 comments on commit be31335

Please sign in to comment.