Skip to content
This repository was archived by the owner on Feb 2, 2021. It is now read-only.

Commit f76634d

Browse files
Merge pull request #313 from telerik/vladimirov/merge-appBuilder-release
Merge release-appbuilder branch after 2.9.0
2 parents d9d09b0 + 8ed5724 commit f76634d

12 files changed

+92
-50
lines changed

commands/preuninstall.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class PreUninstallCommand implements ICommand {
2121
var adbPath = path.join(__dirname, relativeAdbPath);
2222

2323
var killAdbServerCommand = util.format("\"%s\" kill-server", adbPath);
24-
this.$logger.warn("Trying to kill adb server. Some running andorid related operations may fail.");
24+
this.$logger.warn("Trying to kill adb server. Some running Android related operations may fail.");
2525

2626
try {
2727
this.$childProcess.exec(killAdbServerCommand).wait();

declarations.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ interface IHook {
231231
}
232232

233233
interface ITypeScriptCompilationService {
234-
initialize(typeScriptFiles: string[]): void;
234+
initialize(typeScriptFiles: string[], definitionFiles?: string[]): void;
235235
compileAllFiles(): IFuture<void>;
236236
}
237237

definitions/commands-service.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
interface ICommandsService {
2-
allCommands(includeDev: boolean): string[];
2+
allCommands(opts: {includeDevCommands: boolean}): string[];
33
tryExecuteCommand(commandName: string, commandArguments: string[]): IFuture<void>;
44
executeCommandUnchecked(commandName: string, commandArguments: string[]): IFuture<boolean>;
55
completeCommand(): IFuture<boolean>;

definitions/mobile.d.ts

-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ declare module Mobile {
165165
}
166166

167167
interface IHouseArrestClient {
168-
getAfcClientForAppDocuments(applicationIdentifier: string): Mobile.IAfcClient;
169168
getAfcClientForAppContainer(applicationIdentifier: string): Mobile.IAfcClient;
170169
closeSocket(): void;
171170
}

definitions/options-service.d.ts

-3
This file was deleted.

docs/helpers/styles.css

+1
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ ul {
186186
}
187187

188188
ol {
189+
margin: 10px 10px 10px 20px;
189190
list-style-type: decimal;
190191
}
191192

mobile/ios/ios-proxy-services.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,13 @@ export class NotificationProxyClient implements Mobile.INotificationProxyClient
349349

350350
export class HouseArrestClient implements Mobile.IHouseArrestClient {
351351
private plistService: Mobile.IiOSDeviceSocket = null;
352+
private static PREDEFINED_ERRORS: IStringDictionary = {
353+
ApplicationLookupFailed: "Unable to find the application on a connected device. Ensure that the application is installed and try again."
354+
}
352355

353356
constructor(private device: Mobile.IIOSDevice,
354-
private $injector: IInjector) {
357+
private $injector: IInjector,
358+
private $errors: IErrors) {
355359
}
356360

357361
private getAfcClientCore(command: string, applicationIdentifier: string): Mobile.IAfcClient {
@@ -363,15 +367,14 @@ export class HouseArrestClient implements Mobile.IHouseArrestClient {
363367
"Identifier": applicationIdentifier
364368
});
365369

366-
this.plistService.receiveMessage().wait();
370+
var response = this.plistService.receiveMessage().wait();
371+
if(response.Error) {
372+
this.$errors.failWithoutHelp(HouseArrestClient.PREDEFINED_ERRORS[response.Error] || response.Error);
373+
}
367374

368375
return this.$injector.resolve(AfcClient, {service: service});
369376
}
370377

371-
public getAfcClientForAppDocuments(applicationIdentifier: string): Mobile.IAfcClient {
372-
return this.getAfcClientCore("VendDocuments", applicationIdentifier);
373-
}
374-
375378
public getAfcClientForAppContainer(applicationIdentifier: string): Mobile.IAfcClient {
376379
return this.getAfcClientCore("VendContainer", applicationIdentifier);
377380
}

services/auto-completion-service.ts

+29-12
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,11 @@ export class AutoCompletionService implements IAutoCompletionService {
5757

5858
public removeObsoleteAutoCompletion(): IFuture<void> {
5959
return (() => {
60-
// in previous releases we were writing directly in .bash_profile, .bashrc and .zshrc - remove this old code
61-
this.shellProfiles.forEach(file => {
60+
// In previous releases we were writing directly in .bash_profile, .bashrc, .zshrc and .profile - remove this old code
61+
var shellProfilesToBeCleared = this.shellProfiles;
62+
// Add .profile only here as we do not want new autocompletion in this file, but we have to remove our old code from it.
63+
shellProfilesToBeCleared.push(this.getHomePath(".profile"));
64+
shellProfilesToBeCleared.forEach(file => {
6265
try {
6366
var text = this.$fs.readText(file).wait();
6467
var newText = text.replace(this.getTabTabObsoleteRegex(this.$staticConfig.CLIENT_NAME), "");
@@ -72,7 +75,7 @@ export class AutoCompletionService implements IAutoCompletionService {
7275
}
7376
} catch(error) {
7477
if(error.code !== "ENOENT") {
75-
this.$logger.trace("Error while trying to disable autocompletion for '%s' file. Error is:\n%s", error);
78+
this.$logger.trace("Error while trying to disable autocompletion for '%s' file. Error is:\n%s", error.toString());
7679
}
7780
}
7881
});
@@ -145,9 +148,13 @@ export class AutoCompletionService implements IAutoCompletionService {
145148

146149
private isNewAutoCompletionEnabledInFile(fileName: string): IFuture<boolean> {
147150
return ((): boolean => {
148-
var data = this.$fs.readText(fileName).wait();
149-
if(data && data.indexOf(this.completionShellScriptContent) !== -1) {
150-
return true;
151+
try {
152+
var data = this.$fs.readText(fileName).wait();
153+
if(data && data.indexOf(this.completionShellScriptContent) !== -1) {
154+
return true;
155+
}
156+
} catch(err) {
157+
this.$logger.trace("Error while checking is autocompletion enabled in file %s. Error is: '%s'", fileName, err.toString());
151158
}
152159

153160
return false;
@@ -156,8 +163,12 @@ export class AutoCompletionService implements IAutoCompletionService {
156163

157164
private isObsoleteAutoCompletionEnabledInFile(fileName: string): IFuture<boolean> {
158165
return (() => {
159-
var text = this.$fs.readText(fileName).wait();
160-
return text.match(this.getTabTabObsoleteRegex(this.$staticConfig.CLIENT_NAME)) || text.match(this.getTabTabObsoleteRegex(this.$staticConfig.CLIENT_NAME));
166+
try {
167+
var text = this.$fs.readText(fileName).wait();
168+
return text.match(this.getTabTabObsoleteRegex(this.$staticConfig.CLIENT_NAME)) || text.match(this.getTabTabObsoleteRegex(this.$staticConfig.CLIENT_NAME));
169+
} catch(err) {
170+
this.$logger.trace("Error while checking is obsolete autocompletion enabled in file %s. Error is: '%s'", fileName, err.toString());
171+
}
161172
}).future<boolean>()();
162173
}
163174

@@ -169,9 +180,15 @@ export class AutoCompletionService implements IAutoCompletionService {
169180
this.$fs.appendFile(fileName, this.completionShellScriptContent).wait();
170181
this.scriptsUpdated = true;
171182
}
172-
} catch (err) {
173-
this.$logger.out("Failed to update %s. Auto-completion may not work. ", fileName);
174-
this.$logger.out(err);
183+
} catch(err) {
184+
this.$logger.out("Unable to update %s. Command-line completion might not work.", fileName);
185+
// When npm is installed with sudo, in some cases the installation cannot write to shell profiles
186+
// Advise the user how to enable autocompletion after the installation is completed.
187+
if(err.code === "EPERM" && !hostInfo.isWindows() && process.env.SUDO_USER) {
188+
this.$logger.out("To enable command-line completion, run '$ %s autocomplete enable'.", this.$staticConfig.CLIENT_NAME);
189+
}
190+
191+
this.$logger.trace(err);
175192
this.scriptsOk = false;
176193
}
177194
}).future<void>()();
@@ -223,7 +240,7 @@ export class AutoCompletionService implements IAutoCompletionService {
223240
}
224241
} catch(err) {
225242
this.$logger.out("Failed to update %s. Auto-completion may not work. ", filePath);
226-
this.$logger.out(err);
243+
this.$logger.trace(err);
227244
this.scriptsOk = false;
228245
}
229246
}).future<void>()();

services/commands-service.ts

+21-11
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import os = require("os");
88
var options: any = require("../options");
99

1010
class CommandArgumentsValidationHelper {
11-
constructor(public isValid: boolean, public remainingArguments: string[]) { }
11+
constructor(public isValid: boolean, _remainingArguments: string[]) {
12+
this.remainingArguments = _remainingArguments.slice();
13+
}
14+
15+
public remainingArguments: string[];
1216
}
1317

1418
export class CommandsService implements ICommandsService {
@@ -25,8 +29,8 @@ export class CommandsService implements ICommandsService {
2529
private $commandsServiceProvider: ICommandsServiceProvider) {
2630
}
2731

28-
public allCommands(includeDev: boolean): string[] {
29-
var commands = this.$injector.getRegisteredCommandsNames(includeDev);
32+
public allCommands(opts: {includeDevCommands: boolean}): string[] {
33+
var commands = this.$injector.getRegisteredCommandsNames(opts.includeDevCommands);
3034
return _.reject(commands, (command) => _.contains(command, '|'));
3135
}
3236

@@ -144,7 +148,7 @@ export class CommandsService implements ICommandsService {
144148
var argument = _.find(commandArgsHelper.remainingArguments, c => mandatoryParam.validate(c).wait());
145149

146150
if(argument) {
147-
commandArgsHelper.remainingArguments = _.without(commandArgsHelper.remainingArguments, argument);
151+
helpers.remove(commandArgsHelper.remainingArguments, arg => arg === argument);
148152
}
149153
else {
150154
this.$errors.fail("Missing mandatory parameter.");
@@ -190,7 +194,7 @@ export class CommandsService implements ICommandsService {
190194
}
191195

192196
private tryMatchCommand(commandName: string): void {
193-
var allCommands = this.allCommands(false);
197+
var allCommands = this.allCommands({includeDevCommands: false});
194198
var similarCommands: ISimilarCommand[] = [];
195199
_.each(allCommands, (command) => {
196200
if(!this.$injector.isDefaultCommand(command)) {
@@ -230,14 +234,20 @@ export class CommandsService implements ICommandsService {
230234

231235
var childrenCommands = this.$injector.getChildrenCommandsNames(commandName);
232236

233-
if(data.words === 1) {
234-
return tabtab.log(this.allCommands(false), data);
237+
if(data.last && _.startsWith(data.last, "--")) {
238+
return tabtab.log(_.keys(options.knownOpts), data, "--");
235239
}
236240

237-
if(data.last.startsWith("--")) {
238-
// Resolve optionsService here. It is not part of common lib, because we need all knownOptions for each CLI.
239-
var optionsService: IOptionsService = this.$injector.resolve("optionsService");
240-
return tabtab.log(optionsService.getKnownOptions(), data, "--");
241+
if(data.last && _.startsWith(data.last, "-")) {
242+
return tabtab.log(_.keys(options.shorthands), data, "-");
243+
}
244+
245+
if(data.words === 1) {
246+
var allCommands = this.allCommands({includeDevCommands: false});
247+
if(_.startsWith(data.last, this.$commandsServiceProvider.dynamicCommandsPrefix)) {
248+
allCommands = allCommands.concat(this.$commandsServiceProvider.getDynamicCommands().wait());
249+
}
250+
return tabtab.log(allCommands, data);
241251
}
242252

243253
if(data.words >= 3) { // Hierarchical command

services/html-help-service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export class HtmlHelpService implements IHtmlHelpService {
1616
private static RELATIVE_PATH_TO_STYLES_CSS_REGEX = /@RELATIVE_PATH_TO_STYLES_CSS@/g;
1717
private static RELATIVE_PATH_TO_IMAGES_REGEX = /@RELATIVE_PATH_TO_IMAGES@/g;
1818
private static RELATIVE_PATH_TO_INDEX_REGEX = /@RELATIVE_PATH_TO_INDEX@/g;
19-
private static MARKDROWN_LINK_REGEX = /\[([\s\S]+?)\]\([\s\S]*?\)/g;
19+
private static MARKDOWN_LINK_REGEX = /\[([\w -`<>]+?)\]\([\s\S]*?\)/g;
2020

2121
private pathToManPages: string;
2222
private pathToHtmlPages: string;
@@ -152,7 +152,7 @@ export class HtmlHelpService implements IHtmlHelpService {
152152
var helpText = this.readMdFileForCommand(commandName).wait();
153153
var outputText = this.$microTemplateService.parseContent(helpText, { isHtml: false })
154154
.replace(/&nbsp;/g, " ")
155-
.replace(HtmlHelpService.MARKDROWN_LINK_REGEX, "$1");
155+
.replace(HtmlHelpService.MARKDOWN_LINK_REGEX, "$1");
156156

157157
var opts = {
158158
unescape: true,

services/typescript-compilation-service.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@ interface ITypeScriptCompilerMessages {
1717

1818
export class TypeScriptCompilationService implements ITypeScriptCompilationService {
1919
private typeScriptFiles: string[];
20+
private definitionFiles: string[];
2021

2122
constructor(private $childProcess: IChildProcess,
2223
private $fs: IFileSystem,
2324
private $logger: ILogger,
2425
private $config: Config.IConfig) { }
2526

26-
public initialize(typeScriptFiles: string[]): void {
27+
public initialize(typeScriptFiles: string[], definitionFiles?: string[]): void {
2728
this.typeScriptFiles = typeScriptFiles;
29+
this.definitionFiles = definitionFiles || [];
2830
}
2931

3032
public compileAllFiles(): IFuture<void> {
@@ -194,11 +196,14 @@ export class TypeScriptCompilationService implements ITypeScriptCompilationServi
194196

195197
private getTypeScriptDefinitionsFiles(): IFuture<string[]> {
196198
return (() => {
197-
var typeScriptDefinitionsFilesPath = path.join(__dirname, "../../../resources/typescript-definitions-files");
198-
var definitionsFiles = this.$fs.readDirectory(typeScriptDefinitionsFilesPath).wait();
199-
return _.map(definitionsFiles, (definitionFilePath: string) => {
200-
return path.join(typeScriptDefinitionsFilesPath, definitionFilePath);
201-
});
199+
var defaultTypeScriptDefinitionsFilesPath = path.join(__dirname, "../../../resources/typescript-definitions-files");
200+
var defaultDefinitionsFiles = this.$fs.readDirectory(defaultTypeScriptDefinitionsFilesPath).wait();
201+
202+
// Exclude definition files from default path, which are already part of the project (check only the name of the file)
203+
var remainingDefaultDefinitionFiles = _.filter(defaultDefinitionsFiles, defFile => !_.any(this.definitionFiles, f => path.basename(f) === defFile));
204+
return _.map(remainingDefaultDefinitionFiles,(definitionFilePath: string) => {
205+
return path.join(defaultTypeScriptDefinitionsFilesPath, definitionFilePath);
206+
}).concat(this.definitionFiles);
202207
}).future<string[]>()();
203208
}
204209
}

yok.ts

+16-6
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ export class Yok implements IInjector {
227227
commandName = this.getHierarchicalCommandName(name, defaultCommand);
228228
} else {
229229
commandName = "help";
230+
231+
// Show command-line help
232+
var options = require("./options");
233+
options.help = true;
230234
}
231235
}
232236

@@ -259,12 +263,18 @@ export class Yok implements IInjector {
259263
// Check if the default command accepts arguments - if no, return false;
260264
var defaultCommandName = this.getDefaultCommand(commandName);
261265
var defaultCommand = this.resolveCommand(util.format("%s|%s", commandName, defaultCommandName));
262-
if(defaultCommand && defaultCommand.allowedParameters.length > 0) {
263-
return true;
264-
} else {
265-
var errors = $injector.resolve("errors");
266-
errors.fail("The input is not valid sub-command for '%s' command", commandName);
267-
}
266+
if(defaultCommand) {
267+
if (defaultCommand.canExecute) {
268+
return defaultCommand.canExecute(commandArguments).wait();
269+
}
270+
271+
if (defaultCommand.allowedParameters.length > 0) {
272+
return true;
273+
}
274+
}
275+
276+
var errors = $injector.resolve("errors");
277+
errors.fail("The input is not valid sub-command for '%s' command", commandName);
268278
}
269279

270280
return true;

0 commit comments

Comments
 (0)