| /*--------------------------------------------------------- | |
| * 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(); | |
| } | |
| env['GOPATH'] = toolsGopath; | |
| // Explicitly set 'auto' so tools that require | |
| // a newer toolchain can be built. | |
| // We don't use unset, but unconditionally set this env var | |
| // since some users may change the env var using GOENV, | |
| // GOROOT/.goenv, or toolchain modification. | |
| env['GOTOOLCHAIN'] = 'auto'; | |
| // 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; | |
| } | |
| } |