blob: 138dcac760fdb84646843de6808526c00ef7a51f [file] [log] [blame]
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------*/
'use strict';
import vscode = require('vscode');
import { getGoConfig } from './config';
import { getCurrentGoPath, getToolsGopath, resolvePath, substituteEnv } from './util';
import { dirExists } from './utils/pathUtils';
import { getFromGlobalState, updateGlobalState } from './stateUtils';
import { outputChannel } from './goStatus';
// toolInstallationEnvironment returns the environment in which tools should
// be installed. It always returns a new object.
export function toolInstallationEnvironment(): NodeJS.Dict<string> {
const env = newEnvironment();
// If the go.toolsGopath is set, use its value as the GOPATH for `go` processes.
// Else use the Current Gopath
let toolsGopath = getToolsGopath();
if (toolsGopath) {
// User has explicitly chosen to use toolsGopath, so ignore GOBIN.
env['GOBIN'] = '';
} else {
toolsGopath = getCurrentGoPath();
}
if (!toolsGopath) {
const msg = 'Cannot install Go tools. Set either go.gopath or go.toolsGopath in settings.';
vscode.window.showInformationMessage(msg, 'Open User Settings', 'Open Workspace Settings').then((selected) => {
switch (selected) {
case 'Open User Settings':
vscode.commands.executeCommand('workbench.action.openGlobalSettings');
break;
case 'Open Workspace Settings':
vscode.commands.executeCommand('workbench.action.openWorkspaceSettings');
break;
}
});
return {};
}
env['GOPATH'] = toolsGopath;
// Unset env vars that would affect tool build process: 'GOROOT', 'GOOS', 'GOARCH', ...
// Tool installation should be done for the host OS/ARCH (GOHOSTOS/GOHOSTARCH) with
// the default setup.
delete env['GOOS'];
delete env['GOARCH'];
delete env['GOROOT'];
delete env['GOFLAGS'];
delete env['GOENV'];
delete env['GO111MODULE']; // we require module mode (default) for tools installation.
return env;
}
// toolExecutionEnvironment returns the environment in which tools should
// be executed. It always returns a new object.
export function toolExecutionEnvironment(uri?: vscode.Uri, addProcessEnv = true): NodeJS.Dict<string> {
const env = newEnvironment(uri, addProcessEnv);
const gopath = getCurrentGoPath(uri);
if (gopath) {
env['GOPATH'] = gopath;
}
// Remove json flag (-json or --json=<any>) from GOFLAGS because it will effect to result format of the execution
if (env['GOFLAGS'] && env['GOFLAGS'].includes('-json')) {
env['GOFLAGS'] = env['GOFLAGS'].replace(/(^|\s+)-?-json[^\s]*/g, '');
outputChannel.debug(`removed -json from GOFLAGS: ${env['GOFLAGS']}`);
}
return env;
}
function newEnvironment(uri?: vscode.Uri, addProcessEnv = true): NodeJS.Dict<string> {
const toolsEnvVars = getGoConfig(uri)['toolsEnvVars'];
const env = addProcessEnv ? Object.assign({}, process.env) : {};
if (toolsEnvVars && typeof toolsEnvVars === 'object') {
Object.keys(toolsEnvVars).forEach(
(key) =>
(env[key] =
typeof toolsEnvVars[key] === 'string'
? resolvePath(substituteEnv(toolsEnvVars[key]))
: toolsEnvVars[key])
);
}
// The http.proxy setting takes precedence over environment variables.
const httpProxy = vscode.workspace.getConfiguration('http', null).get('proxy');
if (httpProxy && typeof httpProxy === 'string') {
env['http_proxy'] = httpProxy;
env['HTTP_PROXY'] = httpProxy;
env['https_proxy'] = httpProxy;
env['HTTPS_PROXY'] = httpProxy;
}
return env;
}
// set GOROOT env var. If necessary, shows a warning.
export async function setGOROOTEnvVar(configGOROOT: string) {
if (!configGOROOT) {
return;
}
const goroot = configGOROOT ? resolvePath(substituteEnv(configGOROOT)) : undefined;
const currentGOROOT = process.env['GOROOT'];
if (goroot === currentGOROOT) {
return;
}
if (!(await dirExists(goroot ?? ''))) {
vscode.window.showWarningMessage(`go.goroot setting is ignored. ${goroot} is not a valid GOROOT directory.`);
return;
}
const neverAgain = { title: "Don't Show Again" };
const ignoreGOROOTSettingWarningKey = 'ignoreGOROOTSettingWarning';
const ignoreGOROOTSettingWarning = getFromGlobalState(ignoreGOROOTSettingWarningKey);
if (!ignoreGOROOTSettingWarning) {
vscode.window
.showInformationMessage(
`"go.goroot" setting (${goroot}) will be applied and set the GOROOT environment variable.`,
neverAgain
)
.then((result) => {
if (result === neverAgain) {
updateGlobalState(ignoreGOROOTSettingWarningKey, true);
}
});
}
outputChannel.debug(
`setting GOROOT = ${goroot} (old value: ${currentGOROOT}) because "go.goroot": "${configGOROOT}"`
);
if (goroot) {
process.env['GOROOT'] = goroot;
} else {
delete process.env.GOROOT;
}
}