Skip to content

Commit 631960d

Browse files
committed
Merge remote-tracking branch 'origin/master' into patch-1
2 parents d87639f + ff91c18 commit 631960d

File tree

4 files changed

+134
-24
lines changed

4 files changed

+134
-24
lines changed

src/chrome-finder.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {execSync, execFileSync} from 'child_process';
1212
import escapeRegExp = require('escape-string-regexp');
1313
const log = require('lighthouse-logger');
1414

15-
import {getLocalAppDataPath, ChromePathNotSetError} from './utils';
15+
import {getWSLLocalAppDataPath, toWSLPath, ChromePathNotSetError} from './utils';
1616

1717
const newLineRegex = /\r?\n/;
1818

@@ -175,9 +175,10 @@ export function linux() {
175175

176176
export function wsl() {
177177
// Manually populate the environment variables assuming it's the default config
178-
process.env.LOCALAPPDATA = getLocalAppDataPath(`${process.env.PATH}`);
179-
process.env.PROGRAMFILES = '/mnt/c/Program Files';
180-
process.env['PROGRAMFILES(X86)'] = '/mnt/c/Program Files (x86)';
178+
process.env.LOCALAPPDATA = getWSLLocalAppDataPath(`${process.env.PATH}`);
179+
process.env.PROGRAMFILES = toWSLPath('C:/Program Files', '/mnt/c/Program Files');
180+
process.env['PROGRAMFILES(X86)'] =
181+
toWSLPath('C:/Program Files (x86)', '/mnt/c/Program Files (x86)');
181182

182183
return win32();
183184
}

src/chrome-launcher.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import * as net from 'net';
1111
import * as chromeFinder from './chrome-finder';
1212
import {getRandomPort} from './random-port';
1313
import {DEFAULT_FLAGS} from './flags';
14-
import {makeTmpDir, defaults, delay, getPlatform, toWinDirFormat, InvalidUserDataDirectoryError, UnsupportedPlatformError, ChromeNotInstalledError} from './utils';
14+
import {makeTmpDir, defaults, delay, getPlatform, toWin32Path, InvalidUserDataDirectoryError, UnsupportedPlatformError, ChromeNotInstalledError} from './utils';
1515
import {ChildProcess} from 'child_process';
1616
const log = require('lighthouse-logger');
1717
const spawn = childProcess.spawn;
@@ -172,7 +172,7 @@ class Launcher {
172172
if (!this.useDefaultProfile) {
173173
// Place Chrome profile in a custom location we'll rm -rf later
174174
// If in WSL, we need to use the Windows format
175-
flags.push(`--user-data-dir=${isWsl ? toWinDirFormat(this.userDataDir) : this.userDataDir}`);
175+
flags.push(`--user-data-dir=${isWsl ? toWin32Path(this.userDataDir) : this.userDataDir}`);
176176
}
177177

178178
flags.push(...this.chromeFlags);

src/utils.ts

+33-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
'use strict';
77

88
import {join} from 'path';
9-
import {execSync} from 'child_process';
9+
import {execSync, execFileSync} from 'child_process';
1010
import {mkdirSync} from 'fs';
1111
import isWsl = require('is-wsl');
1212

@@ -65,16 +65,17 @@ export function makeTmpDir() {
6565
return makeUnixTmpDir();
6666
case 'wsl':
6767
// We populate the user's Windows temp dir so the folder is correctly created later
68-
process.env.TEMP = getLocalAppDataPath(`${process.env.PATH}`);
68+
process.env.TEMP = getWSLLocalAppDataPath(`${process.env.PATH}`);
6969
case 'win32':
7070
return makeWin32TmpDir();
7171
default:
7272
throw new UnsupportedPlatformError();
7373
}
7474
}
7575

76-
export function toWinDirFormat(dir: string = ''): string {
76+
function toWinDirFormat(dir: string = ''): string {
7777
const results = /\/mnt\/([a-z])\//.exec(dir);
78+
7879
if (!results) {
7980
return dir;
8081
}
@@ -84,13 +85,41 @@ export function toWinDirFormat(dir: string = ''): string {
8485
.replace(/\//g, '\\');
8586
}
8687

87-
export function getLocalAppDataPath(path: string): string {
88+
export function toWin32Path(dir: string = ''): string {
89+
if (/[a-z]:\\/iu.test(dir)) {
90+
return dir;
91+
}
92+
93+
try {
94+
return execFileSync('wslpath', ['-w', dir]).toString().trim();
95+
} catch {
96+
return toWinDirFormat(dir);
97+
}
98+
}
99+
100+
export function toWSLPath(dir: string, fallback: string): string {
101+
try {
102+
return execFileSync('wslpath', ['-u', dir]).toString().trim();
103+
} catch {
104+
return fallback;
105+
}
106+
}
107+
108+
function getLocalAppDataPath(path: string): string {
88109
const userRegExp = /\/mnt\/([a-z])\/Users\/([^\/:]+)\/AppData\//;
89110
const results = userRegExp.exec(path) || [];
90111

91112
return `/mnt/${results[1]}/Users/${results[2]}/AppData/Local`;
92113
}
93114

115+
export function getWSLLocalAppDataPath(path: string): string {
116+
const userRegExp = /\/([a-z])\/Users\/([^\/:]+)\/AppData\//;
117+
const results = userRegExp.exec(path) || [];
118+
119+
return toWSLPath(
120+
`${results[1]}:\\Users\\${results[2]}\\AppData\\Local`, getLocalAppDataPath(path));
121+
}
122+
94123
function makeUnixTmpDir() {
95124
return execSync('mktemp -d -t lighthouse.XXXXXXX').toString().trim();
96125
}

test/utils-test.ts

+94-14
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,104 @@
1616
'use strict';
1717

1818
import * as assert from 'assert';
19-
import {toWinDirFormat, getLocalAppDataPath} from '../src/utils';
19+
import { toWin32Path, toWSLPath, getWSLLocalAppDataPath } from '../src/utils';
20+
import * as sinon from 'sinon';
21+
import * as child_process from 'child_process';
2022

21-
describe('WSL path format to Windows', () => {
22-
it('transforms basic path', () => {
23-
const wsl = '/mnt/c/Users/user1/AppData/';
24-
const windows = 'C:\\Users\\user1\\AppData\\';
25-
assert.strictEqual(toWinDirFormat(wsl), windows);
26-
});
23+
const execFileSyncStub = sinon.stub(child_process, 'execFileSync').callThrough();
24+
25+
const asBuffer = (str: string): Buffer => Buffer.from(str, 'utf-8');
26+
27+
describe('toWin32Path', () => {
28+
beforeEach(() => execFileSyncStub.reset());
29+
30+
it('calls toWin32Path -w', () => {
31+
execFileSyncStub.returns(asBuffer(''));
32+
33+
toWin32Path('');
34+
35+
assert.ok(execFileSyncStub.calledWith('wslpath', ['-w', '']));
36+
})
37+
38+
describe('when the path is already in Windows format', () => {
39+
it('returns early', () => {
40+
execFileSyncStub.returns(asBuffer(''));
2741

28-
it('transforms if drive letter is different than c', () => {
29-
const wsl = '/mnt/d/Users/user1/AppData';
30-
const windows = 'D:\\Users\\user1\\AppData';
31-
assert.strictEqual(toWinDirFormat(wsl), windows);
42+
assert.strictEqual(toWin32Path('D:\\'), 'D:\\');
43+
assert.strictEqual(toWin32Path('C:\\'), 'C:\\');
44+
45+
assert.ok(execFileSyncStub.notCalled);
46+
});
47+
})
48+
49+
describe('when wslpath is not available', () => {
50+
beforeEach(() => execFileSyncStub.throws(new Error('oh noes!')));
51+
52+
it('falls back to the toWinDirFormat method', () => {
53+
const wsl = '/mnt/c/Users/user1/AppData/';
54+
const windows = 'C:\\Users\\user1\\AppData\\';
55+
56+
assert.strictEqual(toWin32Path(wsl), windows);
57+
});
58+
59+
it('supports the drive letter not being C', () => {
60+
const wsl = '/mnt/d/Users/user1/AppData';
61+
const windows = 'D:\\Users\\user1\\AppData';
62+
63+
assert.strictEqual(toWin32Path(wsl), windows);
64+
})
3265
});
66+
})
67+
68+
describe('toWSLPath', () => {
69+
beforeEach(() => execFileSyncStub.reset());
70+
71+
it('calls wslpath -u', () => {
72+
execFileSyncStub.returns(asBuffer(''));
73+
74+
toWSLPath('', '');
75+
76+
assert.ok(execFileSyncStub.calledWith('wslpath', ['-u', '']));
77+
})
78+
79+
it('trims off the trailing newline', () => {
80+
execFileSyncStub.returns(asBuffer('the-path\n'));
81+
82+
assert.strictEqual(toWSLPath('', ''), 'the-path');
83+
})
84+
85+
describe('when wslpath is not available', () => {
86+
beforeEach(() => execFileSyncStub.throws(new Error('oh noes!')));
87+
88+
it('uses the fallback path', () => {
89+
assert.strictEqual(
90+
toWSLPath('C:/Program Files', '/mnt/c/Program Files'),
91+
'/mnt/c/Program Files'
92+
);
93+
})
94+
})
95+
})
96+
97+
describe('getWSLLocalAppDataPath', () => {
98+
beforeEach(() => execFileSyncStub.reset());
99+
100+
it('transforms it to a Linux path using wslpath', () => {
101+
execFileSyncStub.returns(asBuffer('/c/folder/'));
33102

34-
it('getLocalAppDataPath returns a correct path', () => {
35103
const path = '/mnt/c/Users/user1/.bin:/mnt/c/Users/user1:/mnt/c/Users/user1/AppData/';
36-
const appDataPath = '/mnt/c/Users/user1/AppData/Local';
37-
assert.strictEqual(getLocalAppDataPath(path), appDataPath);
104+
105+
assert.strictEqual(getWSLLocalAppDataPath(path), '/c/folder/');
106+
assert.ok(execFileSyncStub.calledWith('wslpath', ['-u', 'c:\\Users\\user1\\AppData\\Local']));
107+
});
108+
109+
describe('when wslpath is not available', () => {
110+
beforeEach(() => execFileSyncStub.throws(new Error('oh noes!')));
111+
112+
it('falls back to the getLocalAppDataPath method', () => {
113+
const path = '/mnt/c/Users/user1/.bin:/mnt/c/Users/user1:/mnt/c/Users/user1/AppData/';
114+
const appDataPath = '/mnt/c/Users/user1/AppData/Local';
115+
116+
assert.strictEqual(getWSLLocalAppDataPath(path), appDataPath);
117+
});
38118
});
39119
});

0 commit comments

Comments
 (0)