Skip to content
This repository has been archived by the owner on Feb 16, 2024. It is now read-only.

Commit

Permalink
Add Windows support to VSCE (#859)
Browse files Browse the repository at this point in the history
* fx

* wip

* prettier

* wip

* finalize

* prettier

* fix

* fix path

* prettier + update version

* spellcheck
  • Loading branch information
DmytroHryshyn authored Jan 26, 2024
1 parent c6b7956 commit b79df36
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 60 deletions.
3 changes: 2 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"POSTAMBLE",
"INTC",
"INTJ",
"INTE"
"INTE",
"Crossplatform"
]
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "intuita-vscode-extension",
"displayName": "Intuita",
"description": " Discover, run & manage codemods faster & easier.",
"version": "0.38.9",
"version": "0.38.10",
"publisher": "Intuita",
"icon": "img/intuita_square128.png",
"repository": {
Expand Down
14 changes: 11 additions & 3 deletions src/components/bootstrapExecutablesService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,22 @@ export class BootstrapExecutablesService {
const platform =
process.platform === 'darwin'
? 'macos'
: process.platform === 'win32'
? 'win'
: encodeURIComponent(process.platform);

const executableBaseName = `intuita-${platform}`;
const executableExt = process.platform === 'win32' ? '.exe' : '';
const executableName = `${executableBaseName}${executableExt}`;

const executableUri = Uri.joinPath(
this.__globalStorageUri,
executableBaseName,
executableName,
);

try {
await this.__downloadService.downloadFileIfNeeded(
`https://intuita-public.s3.us-west-1.amazonaws.com/intuita/${executableBaseName}`,
`https://intuita-public.s3.us-west-1.amazonaws.com/intuita/${executableName}`,
executableUri,
'755',
);
Expand All @@ -65,12 +69,16 @@ export class BootstrapExecutablesService {
return executableUri;
}

private async __bootstrapCodemodEngineRustExecutableUri(): Promise<Uri> {
private async __bootstrapCodemodEngineRustExecutableUri(): Promise<Uri | null> {
const platform =
process.platform === 'darwin'
? 'macos'
: encodeURIComponent(process.platform);

if (platform === 'win32') {
return null;
}

const executableBaseName = `codemod-engine-rust-${platform}`;

const executableUri = Uri.joinPath(
Expand Down
56 changes: 41 additions & 15 deletions src/components/buildArguments.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { Uri } from 'vscode';
import type { Configuration } from '../configuration';
import type { Message, MessageKind } from './messageBus';
import { singleQuotify } from '../utilities';
import { buildCrossplatformArg } from '../utilities';
import { sep } from 'path';

const buildGlobPattern = (targetUri: Uri, pattern?: string) => {
const { fsPath: targetUriFsPath } = targetUri;

// Glob patterns should always use / as a path separator, even on Windows systems, as \ is used to escape glob characters.
return targetUriFsPath
.split(sep)
.join('/')
.concat(pattern ?? '');
};

export const buildArguments = (
configuration: Configuration,
Expand All @@ -23,37 +34,49 @@ export const buildArguments = (
: [];

if (command.kind === 'executePiranhaRule') {
args.push('-i', singleQuotify(message.targetUri.fsPath));
args.push('-c', singleQuotify(command.configurationUri.fsPath));
args.push('-o', singleQuotify(storageUri.fsPath));
args.push('-i', buildCrossplatformArg(message.targetUri.fsPath));
args.push('-c', buildCrossplatformArg(command.configurationUri.fsPath));
args.push('-o', buildCrossplatformArg(storageUri.fsPath));
args.push('-l', command.language);
args.push(...codemodArguments);
return args;
}

if (command.kind === 'executeCodemod') {
args.push(singleQuotify(command.name));
args.push(buildCrossplatformArg(command.name));
} else {
args.push('--sourcePath', singleQuotify(command.codemodUri.fsPath));
args.push(
'--sourcePath',
buildCrossplatformArg(command.codemodUri.fsPath),
);
args.push('--codemodEngine', 'jscodeshift');
}

args.push('--targetPath', singleQuotify(message.targetUri.fsPath));
args.push('--targetPath', buildCrossplatformArg(message.targetUri.fsPath));

if (message.targetUriIsDirectory) {
configuration.includePatterns.forEach((includePattern) => {
const { fsPath } = Uri.joinPath(message.targetUri, includePattern);

args.push('--include', singleQuotify(fsPath));
args.push(
'--include',
buildCrossplatformArg(
buildGlobPattern(message.targetUri, includePattern),
),
);
});

configuration.excludePatterns.forEach((excludePattern) => {
const { fsPath } = Uri.joinPath(message.targetUri, excludePattern);

args.push('--exclude', singleQuotify(fsPath));
args.push(
'--exclude',
buildCrossplatformArg(
buildGlobPattern(message.targetUri, excludePattern),
),
);
});
} else {
args.push('--include', singleQuotify(message.targetUri.fsPath));
args.push(
'--include',
buildCrossplatformArg(buildGlobPattern(message.targetUri)),
);
}

args.push('--threadCount', String(configuration.workerThreadCount));
Expand All @@ -67,7 +90,10 @@ export const buildArguments = (
args.push('--useCache');

args.push('--dryRun');
args.push('--outputDirectoryPath', singleQuotify(storageUri.fsPath));
args.push(
'--outputDirectoryPath',
buildCrossplatformArg(storageUri.fsPath),
);
args.push(...codemodArguments);
return args;
};
70 changes: 31 additions & 39 deletions src/components/engineService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import { Container } from '../container';
import { buildJobHash } from '../jobs/buildJobHash';
import { Job, JobKind } from '../jobs/types';
import {
buildCrossplatformArg,
buildTypeCodec,
isNeitherNullNorUndefined,
singleQuotify,
streamToString,
} from '../utilities';
import { Message, MessageBus, MessageKind } from './messageBus';
Expand Down Expand Up @@ -244,17 +244,33 @@ export class EngineService {
await this.fetchPrivateCodemods();
}

public isEngineBootstrapped() {
return this.__codemodEngineNodeExecutableUri !== null;
private __getCodemodEngineNodeExecutableCommand() {
if (this.__codemodEngineNodeExecutableUri === null) {
throw new Error('The engines are not bootstrapped.');
}

return buildCrossplatformArg(
this.__codemodEngineNodeExecutableUri.fsPath,
);
}

public async syncRegistry(): Promise<void> {
if (this.__codemodEngineNodeExecutableUri === null) {
private __getCodemodEngineRustExecutableCommand() {
if (this.__codemodEngineRustExecutableUri === null) {
throw new Error('The engines are not bootstrapped.');
}

return buildCrossplatformArg(
this.__codemodEngineRustExecutableUri.fsPath,
);
}

public isEngineBootstrapped() {
return this.__codemodEngineNodeExecutableUri !== null;
}

public async syncRegistry(): Promise<void> {
const childProcess = spawn(
singleQuotify(this.__codemodEngineNodeExecutableUri.fsPath),
this.__getCodemodEngineNodeExecutableCommand(),
['syncRegistry'],
{
stdio: 'pipe',
Expand All @@ -275,16 +291,8 @@ export class EngineService {
}

public async __getCodemodNames(): Promise<ReadonlyArray<string>> {
const executableUri = this.__codemodEngineNodeExecutableUri;

if (executableUri === null) {
throw new EngineNotFoundError(
'The codemod engine node has not been downloaded yet',
);
}

const childProcess = spawn(
singleQuotify(executableUri.fsPath),
this.__getCodemodEngineNodeExecutableCommand(),
['list', '--useJson', '--useCache'],
{
stdio: 'pipe',
Expand All @@ -294,7 +302,6 @@ export class EngineService {
);

const codemodListJSON = await streamToString(childProcess.stdout);

try {
const codemodListOrError = codemodNamesCodec.decode(
JSON.parse(codemodListJSON),
Expand Down Expand Up @@ -531,17 +538,6 @@ export class EngineService {
return;
}

if (
!this.__codemodEngineNodeExecutableUri ||
!this.__codemodEngineRustExecutableUri
) {
await window.showErrorMessage(
'Wait until the engines has been bootstrapped to execute the operation',
);

return;
}

const codemodHash =
message.command.kind === 'executeCodemod' ||
message.command.kind === 'executeLocalCodemod'
Expand Down Expand Up @@ -570,18 +566,14 @@ export class EngineService {
storageUri,
);

const childProcess = spawn(
singleQuotify(
message.command.kind === 'executePiranhaRule'
? this.__codemodEngineRustExecutableUri.fsPath
: this.__codemodEngineNodeExecutableUri.fsPath,
),
args,
{
stdio: 'pipe',
shell: true,
},
);
const executableCommand =
message.command.kind === 'executePiranhaRule'
? this.__getCodemodEngineRustExecutableCommand()
: this.__getCodemodEngineNodeExecutableCommand();
const childProcess = spawn(executableCommand, args, {
stdio: 'pipe',
shell: true,
});

this.__store.dispatch(
actions.setCaseHashInProgress(message.caseHashDigest),
Expand Down
2 changes: 1 addition & 1 deletion src/components/messageBus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export type Message =
| Readonly<{
kind: MessageKind.engineBootstrapped;
codemodEngineNodeExecutableUri: Uri;
codemodEngineRustExecutableUri: Uri;
codemodEngineRustExecutableUri: Uri | null;
}>
| Readonly<{
kind: MessageKind.executeCodemodSet;
Expand Down
6 changes: 6 additions & 0 deletions src/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ export const timeout = (ms: number) =>
export const singleQuotify = (str: string) => `'${str}'`;
export const doubleQuotify = (str: string) => `"${str}"`;

export const buildCrossplatformArg = (str: string) => {
const isWin = process.platform === 'win32';
// remove trailing "\"
return isWin ? doubleQuotify(str.replace(/\\+$/, '')) : singleQuotify(str);
};

export function getUri(
webview: Webview,
extensionUri: Uri,
Expand Down

0 comments on commit b79df36

Please sign in to comment.