Skip to content

Commit 0c735a2

Browse files
committed
Merge branch 'main' into mi/e2e-nb-infra
2 parents e35b821 + 99e482b commit 0c735a2

File tree

14 files changed

+206
-642
lines changed

14 files changed

+206
-642
lines changed

extensions/positron-r/src/interpreter-settings.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import * as path from 'path';
77
import * as vscode from 'vscode';
88
import { LOGGER } from './extension';
9-
import { arePathsSame, isParentPath, untildify } from './path-utils';
9+
import { arePathsSame, isParentPath, normalizeUserPath } from './path-utils';
1010

1111
/**
1212
* Directory(ies) where this user keeps R installations.
@@ -21,7 +21,7 @@ export function userRHeadquarters(): string[] {
2121
return [];
2222
}
2323
const userHqDirs = customRootFolders
24-
.map((item) => untildify(item))
24+
.map((item) => normalizeUserPath(item))
2525
.filter((item) => {
2626
if (path.isAbsolute(item)) {
2727
return true;
@@ -46,7 +46,7 @@ export function userRBinaries(): string[] {
4646
return [];
4747
}
4848
const userBinaries = customBinaries
49-
.map((item) => untildify(item))
49+
.map((item) => normalizeUserPath(item))
5050
.filter((item) => {
5151
if (path.isAbsolute(item)) {
5252
return true;
@@ -72,7 +72,7 @@ function getExcludedInstallations(): string[] {
7272
return [];
7373
}
7474
const excludedPaths = interpretersExclude
75-
.map((item) => untildify(item))
75+
.map((item) => normalizeUserPath(item))
7676
.filter((item) => {
7777
if (path.isAbsolute(item)) {
7878
return true;
@@ -100,7 +100,7 @@ export function getInterpreterOverridePaths(): string[] {
100100
return [];
101101
}
102102
const overridePaths = interpretersOverride
103-
.map((item) => untildify(item))
103+
.map((item) => normalizeUserPath(item))
104104
.filter((item) => {
105105
if (path.isAbsolute(item)) {
106106
return true;
@@ -149,7 +149,7 @@ export function getDefaultInterpreterPath(): string | undefined {
149149
const config = vscode.workspace.getConfiguration('positron.r');
150150
let defaultInterpreterPath = config.get<string>('interpreters.default');
151151
if (defaultInterpreterPath) {
152-
defaultInterpreterPath = untildify(defaultInterpreterPath);
152+
defaultInterpreterPath = normalizeUserPath(defaultInterpreterPath);
153153
if (path.isAbsolute(defaultInterpreterPath)) {
154154
LOGGER.info(`Default R interpreter path specified in 'positron.r.interpreters.default': ${defaultInterpreterPath}`);
155155
return defaultInterpreterPath;

extensions/positron-r/src/path-utils.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,24 @@ export function arePathsSame(path1: string, path2: string): boolean {
3939

4040
/**
4141
* Copied from the function of the same name in extensions/positron-python/src/client/common/helpers.ts.
42+
* NOTE: We do not export this since in all known cases, normalizeUserPath()
43+
* is the better choice.
4244
*/
43-
export function untildify(path: string): string {
45+
function untildify(path: string): string {
4446
return path.replace(/^~($|\/|\\)/, `${os.homedir()}$1`);
4547
}
4648

49+
/**
50+
* Normalizes a user-provided path (e.g., from settings) by expanding tilde (~) to the home
51+
* directory, normalizing path separators, and resolving `.` and `..`. This leaves us with
52+
* more robust and predictable paths in, e.g., the R installation metadata.
53+
* @param filepath The user-provided path to normalize
54+
* @returns The normalized, tilde-expanded, absolute path
55+
*/
56+
export function normalizeUserPath(filepath: string): string {
57+
return path.normalize(untildify(filepath));
58+
}
59+
4760
/**
4861
* Check if a path is a file.
4962
* A combination of isFile and resolveSymbolicLink in extensions/positron-python/src/client/pythonEnvironments/common/externalDependencies.ts.

extensions/positron-r/src/r-installation.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ export class RInstallation {
146146
current: boolean = false,
147147
reasonDiscovered: ReasonDiscovered[] | null = null
148148
) {
149+
pth = path.normalize(pth);
150+
149151
LOGGER.info(`Candidate R binary at ${pth}`);
150152

151153
this.binpath = pth;

extensions/positron-r/src/tasks.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,12 @@ export async function getRPackageTasks(editorFilePath?: string): Promise<vscode.
8888
{ env: taskEnv }
8989
);
9090
} else {
91-
// The explicit quoting treatment here is also motivated by PowerShell, so make sure to
92-
// test any changes on Windows.
91+
// The explicit quoting treatment here is motivated by problems on
92+
// both bash and PowerShell, on Windows, so make sure to test any
93+
// changes on Windows.
94+
// https://github.com/posit-dev/positron/issues/9216
9395
exec = new vscode.ShellExecution(
94-
binpath,
96+
{ value: binpath, quoting: vscode.ShellQuoting.Strong },
9597
['--quiet', '--no-restore', '--no-save', '-e', { value: data.rcode, quoting: vscode.ShellQuoting.Strong }],
9698
{ env: taskEnv }
9799
);

src/vs/workbench/contrib/positronConsole/browser/components/currentWorkingDirectory.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import React, { MouseEvent, useEffect, useRef, useState } from 'react';
1111

1212
// Other dependencies.
1313
import { localize } from '../../../../../nls.js';
14+
import { toSlashes } from '../../../../../base/common/extpath.js';
15+
import { isWindows } from '../../../../../base/common/platform.js';
1416
import { usePositronReactServicesContext } from '../../../../../base/browser/positronReactRendererContext.js';
1517
import { CustomContextMenuItem } from '../../../../browser/positronComponents/customContextMenu/customContextMenuItem.js';
1618
import { usePositronActionBarContext } from '../../../../../platform/positronActionBar/browser/positronActionBarContext.js';
@@ -113,7 +115,7 @@ export const CurrentWorkingDirectory = (props: CurrentWorkingDirectoryProps) =>
113115
>
114116
<span className='codicon codicon-folder' role='presentation' />
115117
<span className='label'>
116-
{props.directoryLabel}
118+
{isWindows ? toSlashes(props.directoryLabel) : props.directoryLabel}
117119
</span>
118120
</div>
119121
);

0 commit comments

Comments
 (0)