Skip to content

Commit

Permalink
refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
ElianHugh committed Jan 8, 2024
1 parent 4f6e16c commit 04aafde
Show file tree
Hide file tree
Showing 13 changed files with 150 additions and 135 deletions.
3 changes: 1 addition & 2 deletions src/executables/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ import { RExecutableService, RExecutableType, WorkspaceExecutableEvent } from '.
import { extensionContext } from '../extension';

export * from './virtual';
export * from './renv';
export * from './util';
export { RExecutableType, VirtualRExecutableType, CondaVirtualRExecutable, MambaVirtualRExecutable } from './service';
export { RExecutableType, VirtualRExecutableType } from './service';

// super class that manages relevant sub classes
export class RExecutableManager {
Expand Down
26 changes: 14 additions & 12 deletions src/executables/service/class.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
'use strict';

import { getRDetailsFromPath} from '../util';
// TODO fix imports

import { getRDetailsFromPath } from '../util';
import { RExecutableRegistry } from './registry';
import { RExecutableType } from './types';
import { isCondaInstallation, condaName, getRDetailsFromCondaMetaHistory, isMambaInstallation } from '../virtual';
import {
isCondaInstallation, isMambaInstallation
} from '../virtual';
import { condaName, getRDetailsFromCondaMetaHistory } from '../virtual/conda';

/**
* Creates and caches instances of RExecutableType
Expand All @@ -12,7 +17,7 @@ import { isCondaInstallation, condaName, getRDetailsFromCondaMetaHistory, isMamb
export class RExecutableFactory {
private readonly registry: RExecutableRegistry;

constructor(registry: RExecutableRegistry) {
constructor (registry: RExecutableRegistry) {
this.registry = registry;
}

Expand Down Expand Up @@ -55,7 +60,7 @@ export abstract class AbstractRExecutable {


export class RExecutable extends AbstractRExecutable {
constructor(executablePath: string) {
constructor (executablePath: string) {
super();
const details = getRDetailsFromPath(executablePath);
this._rBin = executablePath;
Expand Down Expand Up @@ -85,7 +90,7 @@ export abstract class AbstractVirtualRExecutable extends AbstractRExecutable {
}

export class CondaVirtualRExecutable extends AbstractVirtualRExecutable {
constructor(executablePath: string) {
constructor (executablePath: string) {
super();
this._name = condaName(executablePath);
const details = getRDetailsFromCondaMetaHistory(executablePath);
Expand All @@ -96,13 +101,10 @@ export class CondaVirtualRExecutable extends AbstractVirtualRExecutable {
}

// TODO

export class MambaVirtualRExecutable extends AbstractVirtualRExecutable {
constructor(executablePath: string) {
constructor (executablePath: string) {

Check warning on line 106 in src/executables/service/class.ts

View workflow job for this annotation

GitHub Actions / eslint

'executablePath' is defined but never used
super();
this._name = condaName(executablePath);
const details = getRDetailsFromCondaMetaHistory(executablePath);
this._rVersion = details?.version ?? '';
this._rArch = details?.arch ?? '';
this._rBin = executablePath;
}
}
}

2 changes: 1 addition & 1 deletion src/executables/service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { RExecutablePathStorage } from './pathStorage';
import { RExecutableRegistry } from './registry';
import { TAbstractLocatorService, LocatorServiceFactory } from './locator';
import { RExecutableType, WorkspaceExecutableEvent } from './types';
import { getRenvVersion } from '../renv';
import { getRenvVersion } from '../virtual/renv';
import { homeExtDir } from '../../extension';

export * from './types';
Expand Down
2 changes: 1 addition & 1 deletion src/executables/ui/quickpick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { RExecutableType } from '../service';
import { RExecutableService } from '../service';
import { isVirtual } from '../virtual';
import { getConfigPathWithSubstitution, validateRExecutablePath } from '../util';
import { getRenvVersion } from '../renv';
import { getRenvVersion } from '../virtual/renv';
import { extensionContext } from '../../extension';

enum ExecutableNotifications {
Expand Down
1 change: 1 addition & 0 deletions src/executables/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function getConfigPathWithSubstitution(): string | undefined {
export function getRDetailsFromPath(rPath: string): { version: string, arch: string } {
try {
const path = normaliseRPathString(rPath);
// TODO
const child = spawnSync(path, [`--version`]).output.join('\n');
const versionRegex = /(?<=R\sversion\s)[0-9.]*/g;
const archRegex = /[0-9]*-bit/g;
Expand Down
113 changes: 0 additions & 113 deletions src/executables/virtual.ts

This file was deleted.

51 changes: 51 additions & 0 deletions src/executables/virtual/conda.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as fs from 'fs-extra';
import * as path from 'path';
import { IExecutableDetails, RExecutableType } from '../service';
import { CondaVirtualRExecutable } from '../service/class';

export function isCondaInstallation(executablePath: string): boolean {
return fs.existsSync(condaMetaDirPath(executablePath));
}

export function isCondaExecutable(executable: RExecutableType) {
return executable instanceof CondaVirtualRExecutable;
}

export function getRDetailsFromCondaMetaHistory(executablePath: string): IExecutableDetails {
try {
const reg = new RegExp(/([0-9]{2})::r-base-([0-9.]*)/g);
const historyContent = fs.readFileSync(condaHistoryPath(executablePath))?.toString();
const res = reg.exec(historyContent);
return {
arch: res?.[1] ? `${res[1]}-bit` : '',
version: res?.[2] ? res[2] : ''
};
} catch (error) {
return {
arch: '',
version: ''
};
}
}

export function condaName(executablePath: string): string {
return path.basename(condaPrefixPath(executablePath));
}

function condaPrefixPath(executablePath: string): string {
return path.dirname(condaMetaDirPath(executablePath));
}

function condaMetaDirPath(executablePath: string): string {
let envDir: string = executablePath;
for (let index = 0; index < 4; index++) {
envDir = path.dirname(envDir);
}
return path.join(envDir, 'conda-meta');
}

function condaHistoryPath(executablePath: string): string {
return path.join(condaMetaDirPath(executablePath), 'history');
}


63 changes: 63 additions & 0 deletions src/executables/virtual/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { isCondaExecutable } from './conda';
import { CondaVirtualRExecutable } from '../service/class';
import { isMambaExecutable } from './mamba';
import { MambaVirtualRExecutable } from '../service/class';
import { rExecutableManager } from '../../extension';
import { getRterm } from '../../util';
import { AbstractRExecutable, AbstractVirtualRExecutable , RExecutableType } from '../service';

export * from './conda';
export * from './mamba';
export * from './renv';

export function isVirtual(executable: AbstractRExecutable): executable is AbstractVirtualRExecutable {
return executable instanceof AbstractVirtualRExecutable;
}

export interface IProcessArgs {
cmd: string;
args?: string[];
}

function virtualAwareArgs(
executable: CondaVirtualRExecutable | MambaVirtualRExecutable,
interactive: boolean,
shellArgs: string[] | ReadonlyArray<string>): IProcessArgs {
const rpath = interactive ? getRterm() : executable.rBin;
const cmd: 'conda' | 'mamba' = isCondaExecutable(executable) ? 'conda' :
isMambaExecutable(executable) ? 'mamba' :
(() => { throw 'Unknown virtual executable'; })();

if (!rpath) {
throw 'Bad R executable path';
}

const args = [
'run',
'-n',
executable.name,
...(interactive ? ['--no-capture-output'] : []),
rpath,
...(shellArgs ? shellArgs : [])
];

return {
cmd: cmd,
args: args
};
}

export function setupVirtualAwareProcessArguments(executable: string, interactive: boolean, args?: ReadonlyArray<string>): IProcessArgs;
export function setupVirtualAwareProcessArguments(executable: RExecutableType, interactive: boolean, args?: ReadonlyArray<string>): IProcessArgs;
export function setupVirtualAwareProcessArguments(executable: RExecutableType | string, interactive: boolean, args?: ReadonlyArray<string>): IProcessArgs {
const rexecutable = typeof executable === 'string' ? rExecutableManager?.getExecutableFromPath(executable) : executable;
if (!rexecutable) {
throw 'Bad R executable path';
}
if (isVirtual(rexecutable)) {
const virtualArgs = virtualAwareArgs(rexecutable, interactive, args ?? []);
return { cmd: virtualArgs.cmd, args: virtualArgs.args };
} else {
return { cmd: rexecutable.rBin, args: args?.concat() ?? [] };
}
}
12 changes: 12 additions & 0 deletions src/executables/virtual/mamba.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { RExecutableType } from '../service';
import { MambaVirtualRExecutable } from '../service/class';

export function isMambaExecutable(executable: RExecutableType) {
return executable instanceof MambaVirtualRExecutable;
}

// TODO
export function isMambaInstallation(executablePath: string): boolean {
return executablePath === 'linter appeasement';
}

File renamed without changes.
2 changes: 1 addition & 1 deletion src/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import { RExecutableType, isVirtual, setupVirtualAwareProcessArguments } from './executables';
import { RExecutableType, setupVirtualAwareProcessArguments } from './executables';
import { rExecutableManager } from './extension';


Expand Down
8 changes: 4 additions & 4 deletions src/test/suite/executable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { ExecutableStatusItem } from '../../executables/ui';
import { mockExtensionContext } from '../common';
import { RExecutablePathStorage } from '../../executables/service/pathStorage';
import { DummyMemento } from '../../util';
import { IRunVirtualBinary, RExecutableManager, isCondaExecutable, setupVirtualAwareProcessArguments } from '../../executables';
import { RExecutable, RExecutableService } from '../../executables/service';
import { IProcessArgs, setupVirtualAwareProcessArguments } from '../../executables';
import { RExecutable, RExecutableService, CondaVirtualRExecutable } from '../../executables/service';

const extension_root: string = path.join(__dirname, '..', '..', '..');

Expand Down Expand Up @@ -105,7 +105,7 @@ suite('Virtuals', () => {
sandbox.restore();
});
test('virtual aware args', () => {
let args: IRunVirtualBinary;
let args: IProcessArgs;
const rArgs = ['--vanilla'];

const realExecutable = new RExecutable('/dummy/path/R');
Expand All @@ -117,7 +117,7 @@ suite('Virtuals', () => {
cmd: '/dummy/path/R'
});

const virtualExecutable = new exec.CondaVirtualRExecutable('/dummy/conda/path/R');
const virtualExecutable = new CondaVirtualRExecutable('/dummy/conda/path/R');
args = setupVirtualAwareProcessArguments(virtualExecutable, false, rArgs);
assert.deepEqual(args, {
args: [
Expand Down
2 changes: 1 addition & 1 deletion src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as cp from 'child_process';
import { rGuestService, isGuestSession } from './liveShare';
import { extensionContext, rExecutableManager } from './extension';
import { randomBytes } from 'crypto';
import { isVirtual, RExecutableType, setupVirtualAwareProcessArguments } from './executables';
import { RExecutableType, setupVirtualAwareProcessArguments } from './executables';

export function config(): vscode.WorkspaceConfiguration {
return vscode.workspace.getConfiguration('r');
Expand Down

0 comments on commit 04aafde

Please sign in to comment.