Skip to content

Commit 41c02aa

Browse files
committed
Fixes microsoft#62594: Resolving process task doesn't take task system into account
1 parent fb9e1da commit 41c02aa

6 files changed

Lines changed: 162 additions & 84 deletions

File tree

src/vs/base/node/processes.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import * as path from 'path';
7+
import * as fs from 'fs';
78
import * as cp from 'child_process';
89
import * as nls from 'vs/nls';
910
import { TPromise, TValueCallback, ErrorCallback } from 'vs/base/common/winjs.base';
@@ -400,3 +401,51 @@ export function createQueuedSender(childProcess: cp.ChildProcess): IQueuedSender
400401

401402
return { send };
402403
}
404+
405+
export namespace win32 {
406+
export function findExecutable(command: string, cwd?: string, paths?: string[]): string {
407+
// If we have an absolute path then we take it.
408+
if (path.isAbsolute(command)) {
409+
return command;
410+
}
411+
if (cwd === void 0) {
412+
cwd = process.cwd();
413+
}
414+
let dir = path.dirname(command);
415+
if (dir !== '.') {
416+
// We have a directory and the directory is relative (see above). Make the path absolute
417+
// to the current working directory.
418+
return path.join(cwd, command);
419+
}
420+
if (paths === void 0 && Types.isString(process.env.PATH)) {
421+
paths = process.env.PATH.split(path.delimiter);
422+
}
423+
// No PATH environment. Make path absolute to the cwd.
424+
if (paths === void 0 || paths.length === 0) {
425+
return path.join(cwd, command);
426+
}
427+
// We have a simple file name. We get the path variable from the env
428+
// and try to find the executable on the path.
429+
for (let pathEntry of paths) {
430+
// The path entry is absolute.
431+
let fullPath: string;
432+
if (path.isAbsolute(pathEntry)) {
433+
fullPath = path.join(pathEntry, command);
434+
} else {
435+
fullPath = path.join(cwd, pathEntry, command);
436+
}
437+
if (fs.existsSync(fullPath)) {
438+
return fullPath;
439+
}
440+
let withExtension = fullPath + '.com';
441+
if (fs.existsSync(withExtension)) {
442+
return withExtension;
443+
}
444+
withExtension = fullPath + '.exe';
445+
if (fs.existsSync(withExtension)) {
446+
return withExtension;
447+
}
448+
}
449+
return path.join(cwd, command);
450+
}
451+
}

src/vs/workbench/api/electron-browser/mainThreadTask.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
TaskDefinitionDTO, TaskExecutionDTO, ProcessExecutionOptionsDTO, TaskPresentationOptionsDTO,
3030
ProcessExecutionDTO, ShellExecutionDTO, ShellExecutionOptionsDTO, TaskDTO, TaskSourceDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO
3131
} from 'vs/workbench/api/shared/tasks';
32+
import { ResolveSet, ResolvedVariables } from 'vs/workbench/parts/tasks/common/taskSystem';
3233

3334
namespace TaskExecutionDTO {
3435
export function from(value: TaskExecution): TaskExecutionDTO {
@@ -505,12 +506,18 @@ export class MainThreadTask implements MainThreadTaskShape {
505506
return URI.parse(`${info.scheme}://${info.authority}${path}`);
506507
},
507508
context: this._extHostContext,
508-
resolveVariables: (workspaceFolder: IWorkspaceFolder, variables: Set<string>): Promise<Map<string, string>> => {
509+
resolveVariables: (workspaceFolder: IWorkspaceFolder, toResolve: ResolveSet): TPromise<ResolvedVariables> => {
509510
let vars: string[] = [];
510-
variables.forEach(item => vars.push(item));
511-
return Promise.resolve(this._proxy.$resolveVariables(workspaceFolder.uri, vars)).then(values => {
512-
let result = new Map<string, string>();
513-
Object.keys(values).forEach(key => result.set(key, values[key]));
511+
toResolve.variables.forEach(item => vars.push(item));
512+
return Promise.resolve(this._proxy.$resolveVariables(workspaceFolder.uri, { process: toResolve.process, variables: vars })).then(values => {
513+
let result = {
514+
process: undefined as string,
515+
variables: new Map<string, string>()
516+
};
517+
Object.keys(values.variables).forEach(key => result.variables.set(key, values[key]));
518+
if (Types.isString(values.process)) {
519+
result.process = values.process;
520+
}
514521
return result;
515522
});
516523
}

src/vs/workbench/api/node/extHost.protocol.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ export interface ExtHostTaskShape {
914914
$onDidStartTaskProcess(value: TaskProcessStartedDTO): void;
915915
$onDidEndTaskProcess(value: TaskProcessEndedDTO): void;
916916
$OnDidEndTask(execution: TaskExecutionDTO): void;
917-
$resolveVariables(workspaceFolder: UriComponents, variables: string[]): Thenable<any>;
917+
$resolveVariables(workspaceFolder: UriComponents, toResolve: { process?: { name: string; cwd?: string }, variables: string[] }): Thenable<{ process?: string; variables: { [key: string]: string } }>;
918918
}
919919

920920
export interface IBreakpointDto {

src/vs/workbench/api/node/extHostTask.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import * as path from 'path';
7+
68
import { URI, UriComponents } from 'vs/base/common/uri';
79
import * as nls from 'vs/nls';
810
import * as Objects from 'vs/base/common/objects';
911
import { asThenable } from 'vs/base/common/async';
1012
import { Event, Emitter } from 'vs/base/common/event';
13+
import { win32 } from 'vs/base/node/processes';
1114

1215
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
1316
import * as tasks from 'vs/workbench/parts/tasks/common/tasks';
@@ -883,9 +886,12 @@ export class ExtHostTask implements ExtHostTaskShape {
883886
});
884887
}
885888

886-
public $resolveVariables(uriComponents: UriComponents, variables: string[]): any {
889+
public $resolveVariables(uriComponents: UriComponents, toResolve: { process?: { name: string; cwd?: string; path?: string }, variables: string[] }): Thenable<{ process?: string, variables: { [key: string]: string; } }> {
887890
let uri: URI = URI.revive(uriComponents);
888-
let result: { [key: string]: string; } = Object.create(null);
891+
let result = {
892+
process: undefined as string,
893+
variables: Object.create(null)
894+
};
889895
let workspaceFolder = this._workspaceService.resolveWorkspaceFolder(uri);
890896
let resolver = new ExtHostVariableResolverService(this._workspaceService, this._editorService, this._configurationService);
891897
let ws: IWorkspaceFolder = {
@@ -896,10 +902,24 @@ export class ExtHostTask implements ExtHostTaskShape {
896902
throw new Error('Not implemented');
897903
}
898904
};
899-
for (let variable of variables) {
900-
result[variable] = resolver.resolve(ws, variable);
905+
for (let variable of toResolve.variables) {
906+
result.variables[variable] = resolver.resolve(ws, variable);
907+
}
908+
if (toResolve.process !== void 0) {
909+
let paths: string[] | undefined = undefined;
910+
if (toResolve.process.path !== void 0) {
911+
paths = toResolve.process.path.split(path.delimiter);
912+
for (let i = 0; i < paths.length; i++) {
913+
paths[i] = resolver.resolve(ws, paths[i]);
914+
}
915+
}
916+
result.process = win32.findExecutable(
917+
resolver.resolve(ws, toResolve.process.name),
918+
toResolve.process.cwd !== void 0 ? resolver.resolve(ws, toResolve.process.cwd) : undefined,
919+
paths
920+
);
901921
}
902-
return result;
922+
return Promise.resolve(result);
903923
}
904924

905925
private nextHandle(): number {

src/vs/workbench/parts/tasks/common/taskSystem.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,25 @@ export interface TaskTerminateResponse extends TerminateResponse {
102102
task: Task | undefined;
103103
}
104104

105+
export interface ResolveSet {
106+
process?: {
107+
name: string;
108+
cwd?: string;
109+
path?: string;
110+
};
111+
variables: Set<string>;
112+
}
113+
114+
export interface ResolvedVariables {
115+
process?: string;
116+
variables: Map<string, string>;
117+
}
118+
105119
export interface TaskSystemInfo {
106120
platform: Platform;
107121
context: any;
108122
uriProvider: (this: void, path: string) => URI;
109-
resolveVariables(workspaceFolder: IWorkspaceFolder, variables: Set<string>): TPromise<Map<string, string>>;
123+
resolveVariables(workspaceFolder: IWorkspaceFolder, toResolve: ResolveSet): TPromise<ResolvedVariables>;
110124
}
111125

112126
export interface TaskSystemInfoResovler {

0 commit comments

Comments
 (0)