Skip to content

Commit df943b1

Browse files
Fatme HavaluovaFatme
Fatme Havaluova
authored andcommitted
Fix unit tests
1 parent 4c115e6 commit df943b1

8 files changed

+334
-92
lines changed

lib/definitions/project.d.ts

+6
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,9 @@ interface IPlatformProjectService {
3434
preparePluginNativeCode(pluginData: IPluginData): IFuture<void>;
3535
removePluginNativeCode(pluginData: IPluginData): IFuture<void>;
3636
}
37+
38+
interface IAndroidProjectPropertiesManager {
39+
getProjectReferences(): IFuture<ILibRef[]>;
40+
addProjectReference(referencePath: string): IFuture<void>;
41+
removeProjectReference(referencePath: string): IFuture<void>;
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
///<reference path="../.d.ts"/>
2+
"use strict";
3+
4+
import path = require("path");
5+
6+
export class AndroidProjectPropertiesManager implements IAndroidProjectPropertiesManager {
7+
private static LIBRARY_REFERENCE_KEY_PREFIX = "android.library.reference.";
8+
9+
private _editor: IPropertiesParserEditor = null;
10+
private filePath: string = null;
11+
private projectReferences: ILibRef[];
12+
private dirty = false;
13+
14+
constructor(private $propertiesParser: IPropertiesParser,
15+
private $fs: IFileSystem,
16+
directoryPath: string) {
17+
this.filePath = path.join(directoryPath, "project.properties");
18+
}
19+
20+
public addToPropertyList(key: string, value: string): IFuture<void> {
21+
return (() => {
22+
let editor = this.createEditor().wait();
23+
let i = 1;
24+
while (editor.get(this.buildKeyName(key, i))) {
25+
i++;
26+
}
27+
28+
editor.set(this.buildKeyName(key, i), value);
29+
this.$propertiesParser.saveEditor().wait();
30+
this.dirty = true;
31+
}).future<void>()();
32+
}
33+
34+
public removeFromPropertyList(key: string, value: string): IFuture<void> {
35+
return (() => {
36+
let editor = this.createEditor().wait();
37+
let valueLowerCase = value.toLowerCase();
38+
let i = 1;
39+
let currentValue: any;
40+
while (currentValue = editor.get(this.buildKeyName(key, i))) {
41+
if (currentValue.toLowerCase() === valueLowerCase) {
42+
while (currentValue = editor.get(this.buildKeyName(key, i+1))) {
43+
editor.set(this.buildKeyName(key, i), currentValue);
44+
i++;
45+
}
46+
editor.set(this.buildKeyName(key, i));
47+
break;
48+
}
49+
i++;
50+
}
51+
this.$propertiesParser.saveEditor().wait();
52+
this.dirty = true;
53+
}).future<void>()();
54+
}
55+
56+
public getProjectReferences(): IFuture<ILibRef[]> {
57+
return (() => {
58+
if(!this.projectReferences || this.dirty) {
59+
let allProjectProperties = this.getAllProjectProperties().wait();
60+
let allProjectPropertiesKeys = _.keys(allProjectProperties);
61+
this.projectReferences = _(allProjectPropertiesKeys)
62+
.filter(key => _.startsWith(key, "android.library.reference."))
63+
.map(key => this.createLibraryReference(key, allProjectProperties[key]))
64+
.value();
65+
}
66+
67+
return this.projectReferences;
68+
}).future<ILibRef[]>()();
69+
}
70+
71+
public addProjectReference(referencePath: string): IFuture<void> {
72+
return (() => {
73+
let references = this.getProjectReferences().wait();
74+
let libRefExists = _.any(references, r => path.normalize(r.path) === path.normalize(referencePath));
75+
if(!libRefExists) {
76+
this.addToPropertyList("android.library.reference", referencePath).wait();
77+
}
78+
}).future<void>()();
79+
}
80+
81+
public removeProjectReference(referencePath: string): IFuture<void> {
82+
return (() => {
83+
let references = this.getProjectReferences().wait();
84+
let libRefExists = _.any(references, r => path.normalize(r.path) === path.normalize(referencePath));
85+
if(libRefExists) {
86+
this.removeFromPropertyList("android.library.reference", referencePath).wait();
87+
}
88+
}).future<void>()();
89+
}
90+
91+
private createEditor(): IFuture<any> {
92+
return (() => {
93+
return this._editor || this.$propertiesParser.createEditor(this.filePath).wait();
94+
}).future<any>()();
95+
}
96+
97+
private buildKeyName(key: string, index: number): string {
98+
return `${key}.${index}`;
99+
}
100+
101+
private getAllProjectProperties(): IFuture<IStringDictionary> {
102+
return this.$propertiesParser.read(this.filePath);
103+
}
104+
105+
private createLibraryReference(referenceName: string, referencePath: string): ILibRef {
106+
return {
107+
idx: parseInt(referenceName.split("android.library.reference.")[1]),
108+
key: referenceName,
109+
path: referencePath,
110+
adjustedPath: path.join(path.dirname(this.filePath), referencePath)
111+
}
112+
}
113+
}

lib/services/android-project-service.ts

+61-85
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import helpers = require("../common/helpers");
99
import fs = require("fs");
1010
import os = require("os");
1111

12+
import androidProjectPropertiesManagerLib = require("./android-project-properties-manager");
13+
1214
class AndroidProjectService implements IPlatformProjectService {
1315
private static MIN_SUPPORTED_VERSION = 17;
1416
private SUPPORTED_TARGETS = ["android-17", "android-18", "android-19", "android-21", "android-22"]; // forbidden for now: "android-MNC"
@@ -21,6 +23,7 @@ class AndroidProjectService implements IPlatformProjectService {
2123

2224

2325
private targetApi: string;
26+
private _androidProjectPropertiesManagers: IDictionary<IAndroidProjectPropertiesManager>;
2427

2528
constructor(private $androidEmulatorServices: Mobile.IEmulatorPlatformServices,
2629
private $childProcess: IChildProcess,
@@ -30,7 +33,9 @@ class AndroidProjectService implements IPlatformProjectService {
3033
private $projectData: IProjectData,
3134
private $propertiesParser: IPropertiesParser,
3235
private $options: IOptions,
33-
private $hostInfo: IHostInfo) {
36+
private $hostInfo: IHostInfo,
37+
private $injector: IInjector) {
38+
this._androidProjectPropertiesManagers = Object.create(null);
3439
}
3540

3641
private _platformData: IPlatformData = null;
@@ -185,79 +190,45 @@ class AndroidProjectService implements IPlatformProjectService {
185190
return this.$fs.exists(path.join(projectRoot, "assets", constants.APP_FOLDER_NAME));
186191
}
187192

188-
private parseProjectProperties(projDir: string, destDir: string): IFuture<void> {
193+
private getProjectPropertiesManager(filePath: string): IAndroidProjectPropertiesManager {
194+
if(!this._androidProjectPropertiesManagers[filePath]) {
195+
this._androidProjectPropertiesManagers[filePath] = this.$injector.resolve(androidProjectPropertiesManagerLib.AndroidProjectPropertiesManager, { directoryPath: filePath });
196+
}
197+
198+
return this._androidProjectPropertiesManagers[filePath];
199+
}
200+
201+
private parseProjectProperties(projDir: string, destDir: string): IFuture<void> { // projDir is libraryPath, targetPath is the path to lib folder
189202
return (() => {
190203
let projProp = path.join(projDir, "project.properties");
191-
192204
if (!this.$fs.exists(projProp).wait()) {
193205
this.$logger.warn("Warning: File %s does not exist", projProp);
194206
return;
195207
}
196-
197-
let lines = this.$fs.readText(projProp, "utf-8").wait().split(os.EOL);
198-
199-
let regEx = /android\.library\.reference\.(\d+)=(.*)/;
200-
lines.forEach(elem => {
201-
let match = elem.match(regEx);
202-
if (match) {
203-
let libRef: ILibRef = { idx: parseInt(match[1]), path: match[2].trim() };
204-
libRef.adjustedPath = this.$fs.isRelativePath(libRef.path) ? path.join(projDir, libRef.path) : libRef.path;
205-
this.parseProjectProperties(libRef.adjustedPath, destDir).wait();
206-
}
208+
209+
let projectPropertiesManager = this.getProjectPropertiesManager(projDir);
210+
let references = projectPropertiesManager.getProjectReferences().wait();
211+
_.each(references, reference => {
212+
let adjustedPath = this.$fs.isRelativePath(reference.path) ? path.join(projDir, reference.path) : reference.path;
213+
this.parseProjectProperties(adjustedPath, destDir).wait();
207214
});
208215

209216
this.$logger.info("Copying %s", projDir);
210217
shell.cp("-Rf", projDir, destDir);
211218

212219
let targetDir = path.join(destDir, path.basename(projDir));
213-
// TODO: parametrize targetSdk
214-
let targetSdk = "android-17";
220+
let targetSdk = `android-${this.$options.sdk || 17}`;
215221
this.$logger.info("Generate build.xml for %s", targetDir);
216222
this.runAndroidUpdate(targetDir, targetSdk).wait();
217223
}).future<void>()();
218224
}
219225

220-
private getProjectReferences(projDir: string): ILibRef[]{
221-
let projProp = path.join(projDir, "project.properties");
222-
223-
let lines = this.$fs.readText(projProp, "utf-8").wait().split(os.EOL);
224-
225-
let refs: ILibRef[] = [];
226-
227-
let regEx = /android\.library\.reference\.(\d+)=(.*)/;
228-
lines.forEach(elem => {
229-
let match = elem.match(regEx);
230-
if (match) {
231-
let libRef: ILibRef = { idx: parseInt(match[1]), path: match[2] };
232-
libRef.adjustedPath = path.join(projDir, libRef.path);
233-
libRef.key = match[0].split("=")[0];
234-
refs.push(libRef);
235-
}
236-
});
237-
238-
return refs;
239-
}
240-
241-
private updateProjectReferences(projDir: string, libraryPath: string): void {
242-
let refs = this.getProjectReferences(projDir);
243-
let maxIdx = refs.length > 0 ? _.max(refs, r => r.idx).idx : 0;
244-
245-
let relLibDir = path.relative(projDir, libraryPath).split("\\").join("/");
246-
247-
let libRefExists = _.any(refs, r => path.normalize(r.path) === path.normalize(relLibDir));
248-
249-
if (!libRefExists) {
250-
let projRef = util.format("%sandroid.library.reference.%d=%s", os.EOL, maxIdx + 1, relLibDir);
251-
let projProp = path.join(projDir, "project.properties");
252-
fs.appendFileSync(projProp, projRef, { encoding: "utf-8" });
253-
}
254-
}
255-
256226
public addLibrary(platformData: IPlatformData, libraryPath: string): IFuture<void> {
257227
return (() => {
258228
let name = path.basename(libraryPath);
259-
let projDir = this.$projectData.projectDir;
260-
let targetPath = path.join(projDir, "lib", platformData.normalizedPlatformName);
229+
let targetLibPath = this.getLibraryPath(name);
230+
231+
let targetPath = path.dirname(targetLibPath);
261232
this.$fs.ensureDirectoryExists(targetPath).wait();
262233

263234
this.parseProjectProperties(libraryPath, targetPath).wait();
@@ -267,11 +238,9 @@ class AndroidProjectService implements IPlatformProjectService {
267238
this.$fs.ensureDirectoryExists(projectLibsDir).wait();
268239
shell.cp("-f", path.join(libraryPath, "*.jar"), projectLibsDir);
269240

270-
let targetLibPath = path.join(targetPath, path.basename(libraryPath));
271-
272241
let libProjProp = path.join(libraryPath, "project.properties");
273242
if (this.$fs.exists(libProjProp).wait()) {
274-
this.updateProjectReferences(platformData.projectRoot, targetLibPath);
243+
this.updateProjectReferences(platformData.projectRoot, targetLibPath).wait();
275244
}
276245
}).future<void>()();
277246
}
@@ -290,54 +259,61 @@ class AndroidProjectService implements IPlatformProjectService {
290259
let libsFolderContents = this.$fs.readDirectory(libsFolderPath).wait();
291260
_(libsFolderContents)
292261
.filter(libsFolderItem => path.extname(libsFolderItem) === ".jar")
293-
.map(jar => this.addLibrary(this.platformData, path.join(libsFolderPath, jar)).wait());
262+
.map(jar => this.addLibrary(this.platformData, path.join(libsFolderPath, jar)).wait())
263+
.value();
294264
}
295265

296266
// Handle android libraries
297-
let androidLibraries = this.getAllAndroidLibrariesForPlugin(pluginData).wait();
298-
_.each(androidLibraries, androidLibraryName => this.addLibrary(this.platformData, path.join(pluginPlatformsFolderPath, androidLibraryName)).wait());
299-
267+
let librarries = this.getAllLibrariesForPlugin(pluginData).wait();
268+
_.each(librarries, libraryName => this.addLibrary(this.platformData, path.join(pluginPlatformsFolderPath, libraryName)).wait());
300269
}).future<void>()();
301270
}
302271

303272
public removePluginNativeCode(pluginData: IPluginData): IFuture<void> {
304273
return (() => {
305-
let projectReferences = this.getProjectReferences(this.platformData.projectRoot);
306-
let androidLibraries = this.getAllAndroidLibrariesForPlugin(pluginData).wait();
274+
let projectPropertiesManager = this.getProjectPropertiesManager(this.platformData.projectRoot);
307275

308-
let file = path.join(this.platformData.projectRoot, "project.properties");
309-
let editor = this.$propertiesParser.createEditor(file).wait();
310-
311-
_.each(androidLibraries, androidLibraryName => {
312-
// Remove library from project.properties
313-
let androidLibraryNameLowerCase = androidLibraryName.toLowerCase();
314-
let projectReference = _.find(projectReferences, projectReference => _.last(projectReference.adjustedPath.split(path.sep)).toLowerCase() === androidLibraryNameLowerCase);
315-
if(projectReference && projectReference.key) {
316-
editor.unset(projectReference.key);
317-
}
318-
319-
// Remove library from lib folder
320-
this.$fs.deleteDirectory(path.join(this.$projectData.projectDir, "lib", this.platformData.normalizedPlatformName, androidLibraryName)).wait();
276+
let libraries = this.getAllLibrariesForPlugin(pluginData).wait();
277+
_.each(libraries, libraryName => {
278+
let libPath = this.getLibraryRelativePath(this.platformData.projectRoot, this.getLibraryPath(libraryName));
279+
projectPropertiesManager.removeProjectReference(path.relative(this.platformData.projectRoot, libPath)).wait();
280+
this.$fs.deleteDirectory(libPath).wait();
321281
});
322282

323-
this.$propertiesParser.saveEditor().wait();
324-
325283
}).future<void>()();
326284
}
327285

328286
private getPluginPlatformsFolderPath(pluginData: IPluginData) {
329287
return pluginData.pluginPlatformsFolderPath(AndroidProjectService.ANDROID_PLATFORM_NAME);
330288
}
331289

332-
private getAllAndroidLibrariesForPlugin(pluginData: IPluginData): IFuture<string[]> {
290+
private getLibraryRelativePath(basePath: string, libraryPath: string): string {
291+
return path.relative(basePath, libraryPath).split("\\").join("/");
292+
}
293+
294+
private getLibraryPath(libraryName: string): string {
295+
return path.join(this.$projectData.projectDir, "lib", this.platformData.normalizedPlatformName, libraryName);
296+
}
297+
298+
private updateProjectReferences(projDir: string, libraryPath: string): IFuture<void> {
299+
let relLibDir = this.getLibraryRelativePath(projDir, libraryPath);
300+
301+
let projectPropertiesManager = this.getProjectPropertiesManager(projDir);
302+
return projectPropertiesManager.addProjectReference(relLibDir);
303+
}
304+
305+
private getAllLibrariesForPlugin(pluginData: IPluginData): IFuture<string[]> {
333306
return (() => {
334307
let pluginPlatformsFolderPath = this.getPluginPlatformsFolderPath(pluginData);
335-
let platformsContents = this.$fs.readDirectory(pluginPlatformsFolderPath).wait();
336-
return _(platformsContents)
337-
.filter(platformItemName => platformItemName !== AndroidProjectService.LIBS_FOLDER_NAME &&
338-
this.$fs.exists(path.join(pluginPlatformsFolderPath, platformItemName, "project.properties")).wait())
339-
.map(androidLibraryName => androidLibraryName)
340-
.value();
308+
if(pluginPlatformsFolderPath && this.$fs.exists(pluginPlatformsFolderPath).wait()) {
309+
let platformsContents = this.$fs.readDirectory(pluginPlatformsFolderPath).wait();
310+
return _(platformsContents)
311+
.filter(platformItemName => platformItemName !== AndroidProjectService.LIBS_FOLDER_NAME &&
312+
this.$fs.exists(path.join(pluginPlatformsFolderPath, platformItemName, "project.properties")).wait())
313+
.value();
314+
}
315+
316+
return [];
341317
}).future<string[]>()();
342318
}
343319

lib/services/ios-project-service.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,11 @@ class IOSProjectService implements IPlatformProjectService {
228228
}
229229

230230
public preparePluginNativeCode(pluginData: IPluginData): IFuture<void> {
231-
return (() => {
232-
}).future<void>()();
231+
return Future.fromResult();
233232
}
234233

235234
public removePluginNativeCode(pluginData: IPluginData): IFuture<void> {
236-
return (() => {
237-
}).future<void>()();
235+
return Future.fromResult();
238236
}
239237

240238
private buildPathToXcodeProjectFile(version: string): string {

0 commit comments

Comments
 (0)