Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
connorjclark committed Mar 14, 2022
2 parents d87639f + ff91c18 commit 631960d
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 24 deletions.
9 changes: 5 additions & 4 deletions src/chrome-finder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {execSync, execFileSync} from 'child_process';
import escapeRegExp = require('escape-string-regexp');
const log = require('lighthouse-logger');

import {getLocalAppDataPath, ChromePathNotSetError} from './utils';
import {getWSLLocalAppDataPath, toWSLPath, ChromePathNotSetError} from './utils';

const newLineRegex = /\r?\n/;

Expand Down Expand Up @@ -175,9 +175,10 @@ export function linux() {

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

return win32();
}
Expand Down
4 changes: 2 additions & 2 deletions src/chrome-launcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as net from 'net';
import * as chromeFinder from './chrome-finder';
import {getRandomPort} from './random-port';
import {DEFAULT_FLAGS} from './flags';
import {makeTmpDir, defaults, delay, getPlatform, toWinDirFormat, InvalidUserDataDirectoryError, UnsupportedPlatformError, ChromeNotInstalledError} from './utils';
import {makeTmpDir, defaults, delay, getPlatform, toWin32Path, InvalidUserDataDirectoryError, UnsupportedPlatformError, ChromeNotInstalledError} from './utils';
import {ChildProcess} from 'child_process';
const log = require('lighthouse-logger');
const spawn = childProcess.spawn;
Expand Down Expand Up @@ -172,7 +172,7 @@ class Launcher {
if (!this.useDefaultProfile) {
// Place Chrome profile in a custom location we'll rm -rf later
// If in WSL, we need to use the Windows format
flags.push(`--user-data-dir=${isWsl ? toWinDirFormat(this.userDataDir) : this.userDataDir}`);
flags.push(`--user-data-dir=${isWsl ? toWin32Path(this.userDataDir) : this.userDataDir}`);
}

flags.push(...this.chromeFlags);
Expand Down
37 changes: 33 additions & 4 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
'use strict';

import {join} from 'path';
import {execSync} from 'child_process';
import {execSync, execFileSync} from 'child_process';
import {mkdirSync} from 'fs';
import isWsl = require('is-wsl');

Expand Down Expand Up @@ -65,16 +65,17 @@ export function makeTmpDir() {
return makeUnixTmpDir();
case 'wsl':
// We populate the user's Windows temp dir so the folder is correctly created later
process.env.TEMP = getLocalAppDataPath(`${process.env.PATH}`);
process.env.TEMP = getWSLLocalAppDataPath(`${process.env.PATH}`);
case 'win32':
return makeWin32TmpDir();
default:
throw new UnsupportedPlatformError();
}
}

export function toWinDirFormat(dir: string = ''): string {
function toWinDirFormat(dir: string = ''): string {
const results = /\/mnt\/([a-z])\//.exec(dir);

if (!results) {
return dir;
}
Expand All @@ -84,13 +85,41 @@ export function toWinDirFormat(dir: string = ''): string {
.replace(/\//g, '\\');
}

export function getLocalAppDataPath(path: string): string {
export function toWin32Path(dir: string = ''): string {
if (/[a-z]:\\/iu.test(dir)) {
return dir;
}

try {
return execFileSync('wslpath', ['-w', dir]).toString().trim();
} catch {
return toWinDirFormat(dir);
}
}

export function toWSLPath(dir: string, fallback: string): string {
try {
return execFileSync('wslpath', ['-u', dir]).toString().trim();
} catch {
return fallback;
}
}

function getLocalAppDataPath(path: string): string {
const userRegExp = /\/mnt\/([a-z])\/Users\/([^\/:]+)\/AppData\//;
const results = userRegExp.exec(path) || [];

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

export function getWSLLocalAppDataPath(path: string): string {
const userRegExp = /\/([a-z])\/Users\/([^\/:]+)\/AppData\//;
const results = userRegExp.exec(path) || [];

return toWSLPath(
`${results[1]}:\\Users\\${results[2]}\\AppData\\Local`, getLocalAppDataPath(path));
}

function makeUnixTmpDir() {
return execSync('mktemp -d -t lighthouse.XXXXXXX').toString().trim();
}
Expand Down
108 changes: 94 additions & 14 deletions test/utils-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,104 @@
'use strict';

import * as assert from 'assert';
import {toWinDirFormat, getLocalAppDataPath} from '../src/utils';
import { toWin32Path, toWSLPath, getWSLLocalAppDataPath } from '../src/utils';
import * as sinon from 'sinon';
import * as child_process from 'child_process';

describe('WSL path format to Windows', () => {
it('transforms basic path', () => {
const wsl = '/mnt/c/Users/user1/AppData/';
const windows = 'C:\\Users\\user1\\AppData\\';
assert.strictEqual(toWinDirFormat(wsl), windows);
});
const execFileSyncStub = sinon.stub(child_process, 'execFileSync').callThrough();

const asBuffer = (str: string): Buffer => Buffer.from(str, 'utf-8');

describe('toWin32Path', () => {
beforeEach(() => execFileSyncStub.reset());

it('calls toWin32Path -w', () => {
execFileSyncStub.returns(asBuffer(''));

toWin32Path('');

assert.ok(execFileSyncStub.calledWith('wslpath', ['-w', '']));
})

describe('when the path is already in Windows format', () => {
it('returns early', () => {
execFileSyncStub.returns(asBuffer(''));

it('transforms if drive letter is different than c', () => {
const wsl = '/mnt/d/Users/user1/AppData';
const windows = 'D:\\Users\\user1\\AppData';
assert.strictEqual(toWinDirFormat(wsl), windows);
assert.strictEqual(toWin32Path('D:\\'), 'D:\\');
assert.strictEqual(toWin32Path('C:\\'), 'C:\\');

assert.ok(execFileSyncStub.notCalled);
});
})

describe('when wslpath is not available', () => {
beforeEach(() => execFileSyncStub.throws(new Error('oh noes!')));

it('falls back to the toWinDirFormat method', () => {
const wsl = '/mnt/c/Users/user1/AppData/';
const windows = 'C:\\Users\\user1\\AppData\\';

assert.strictEqual(toWin32Path(wsl), windows);
});

it('supports the drive letter not being C', () => {
const wsl = '/mnt/d/Users/user1/AppData';
const windows = 'D:\\Users\\user1\\AppData';

assert.strictEqual(toWin32Path(wsl), windows);
})
});
})

describe('toWSLPath', () => {
beforeEach(() => execFileSyncStub.reset());

it('calls wslpath -u', () => {
execFileSyncStub.returns(asBuffer(''));

toWSLPath('', '');

assert.ok(execFileSyncStub.calledWith('wslpath', ['-u', '']));
})

it('trims off the trailing newline', () => {
execFileSyncStub.returns(asBuffer('the-path\n'));

assert.strictEqual(toWSLPath('', ''), 'the-path');
})

describe('when wslpath is not available', () => {
beforeEach(() => execFileSyncStub.throws(new Error('oh noes!')));

it('uses the fallback path', () => {
assert.strictEqual(
toWSLPath('C:/Program Files', '/mnt/c/Program Files'),
'/mnt/c/Program Files'
);
})
})
})

describe('getWSLLocalAppDataPath', () => {
beforeEach(() => execFileSyncStub.reset());

it('transforms it to a Linux path using wslpath', () => {
execFileSyncStub.returns(asBuffer('/c/folder/'));

it('getLocalAppDataPath returns a correct path', () => {
const path = '/mnt/c/Users/user1/.bin:/mnt/c/Users/user1:/mnt/c/Users/user1/AppData/';
const appDataPath = '/mnt/c/Users/user1/AppData/Local';
assert.strictEqual(getLocalAppDataPath(path), appDataPath);

assert.strictEqual(getWSLLocalAppDataPath(path), '/c/folder/');
assert.ok(execFileSyncStub.calledWith('wslpath', ['-u', 'c:\\Users\\user1\\AppData\\Local']));
});

describe('when wslpath is not available', () => {
beforeEach(() => execFileSyncStub.throws(new Error('oh noes!')));

it('falls back to the getLocalAppDataPath method', () => {
const path = '/mnt/c/Users/user1/.bin:/mnt/c/Users/user1:/mnt/c/Users/user1/AppData/';
const appDataPath = '/mnt/c/Users/user1/AppData/Local';

assert.strictEqual(getWSLLocalAppDataPath(path), appDataPath);
});
});
});

0 comments on commit 631960d

Please sign in to comment.