mirror of
https://github.com/grumpycoders/pcsx-redux.git
synced 2025-04-02 10:41:54 -04:00
739 lines
23 KiB
JavaScript
739 lines
23 KiB
JavaScript
'use strict'
|
|
|
|
const vscode = require('vscode')
|
|
const util = require('node:util')
|
|
const execFileAsync = require('node:child_process').execFile
|
|
const execFile = util.promisify(execFileAsync)
|
|
const terminal = require('./terminal.js')
|
|
const pcsxRedux = require('./pcsx-redux.js')
|
|
const fs = require('fs-extra')
|
|
const which = require('which')
|
|
const downloader = require('./downloader.js')
|
|
const unzipper = require('unzipper')
|
|
const path = require('node:path')
|
|
const { Octokit } = require('@octokit/rest')
|
|
const octokit = new Octokit()
|
|
const os = require('node:os')
|
|
|
|
const mipsVersion = '14.2.0'
|
|
let extensionUri
|
|
let globalStorageUri
|
|
let requiresReboot = false
|
|
|
|
async function checkInstalled (name) {
|
|
if (tools[name].installed === undefined) {
|
|
tools[name].installed = await tools[name].check()
|
|
}
|
|
return tools[name].installed
|
|
}
|
|
|
|
async function checkCommands (commands, args) {
|
|
for (const command of commands) {
|
|
try {
|
|
await execFile(command, args)
|
|
} catch (error) {
|
|
continue
|
|
}
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
let mipsInstalling = false
|
|
let win32MipsToolsInstalling = false
|
|
|
|
async function installMips () {
|
|
if (mipsInstalling) return
|
|
mipsInstalling = true
|
|
try {
|
|
await terminal.run('powershell', [
|
|
'-c',
|
|
'& { iwr -UseBasicParsing https://raw.githubusercontent.com/grumpycoders/pcsx-redux/main/mips.ps1 | iex }'
|
|
])
|
|
requiresReboot = true
|
|
vscode.window.showInformationMessage(
|
|
'Installing the MIPS tool requires a reboot. Please reboot your computer before proceeding further.'
|
|
)
|
|
} catch (error) {
|
|
vscode.window.showErrorMessage(
|
|
'An error occurred while installing the MIPS toolchain. Please install it manually.'
|
|
)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
async function installToolchain () {
|
|
switch (process.platform) {
|
|
case 'win32':
|
|
try {
|
|
if (!(await checkInstalled('mips'))) {
|
|
await installMips()
|
|
} else {
|
|
if (win32MipsToolsInstalling) return
|
|
win32MipsToolsInstalling = true
|
|
await terminal.run('mips', ['install', mipsVersion])
|
|
}
|
|
} catch (error) {
|
|
vscode.window.showErrorMessage(
|
|
'An error occurred while installing the MIPS toolchain. Please install it manually.'
|
|
)
|
|
throw error
|
|
}
|
|
break
|
|
case 'linux':
|
|
try {
|
|
if (await checkInstalled('apt')) {
|
|
await terminal.run(
|
|
'sudo',
|
|
['apt', 'install', 'g++-mipsel-linux-gnu'],
|
|
{
|
|
message: 'Installing the MIPS toolchain requires root privileges.'
|
|
}
|
|
)
|
|
} else if (await checkInstalled('trizen')) {
|
|
await terminal.run('trizen', [
|
|
'-S',
|
|
'cross-mipsel-linux-gnu-binutils',
|
|
'cross-mipsel-linux-gnu-gcc'
|
|
])
|
|
} else if (await checkInstalled('brew')) {
|
|
const binutilsScriptPath = vscode.Uri.joinPath(
|
|
extensionUri,
|
|
'scripts',
|
|
'mipsel-none-elf-binutils.rb'
|
|
).fsPath
|
|
const gccScriptPath = vscode.Uri.joinPath(
|
|
extensionUri,
|
|
'scripts',
|
|
'mipsel-none-elf-gcc.rb'
|
|
).fsPath
|
|
await terminal.run('brew', [
|
|
'install',
|
|
'--formula',
|
|
binutilsScriptPath,
|
|
gccScriptPath
|
|
])
|
|
} else {
|
|
vscode.window.showErrorMessage(
|
|
'Your Linux distribution is not supported. You need to install the MIPS toolchain manually.'
|
|
)
|
|
throw new Error('Unsupported platform')
|
|
}
|
|
} catch (error) {
|
|
vscode.window.showErrorMessage(
|
|
'An error occurred while installing the MIPS toolchain. Please install it manually.'
|
|
)
|
|
throw error
|
|
}
|
|
break
|
|
case 'darwin':
|
|
try {
|
|
if (await checkInstalled('brew')) {
|
|
const binutilsScriptPath = vscode.Uri.joinPath(
|
|
extensionUri,
|
|
'scripts',
|
|
'mipsel-none-elf-binutils.rb'
|
|
).fsPath
|
|
const gccScriptPath = vscode.Uri.joinPath(
|
|
extensionUri,
|
|
'scripts',
|
|
'mipsel-none-elf-gcc.rb'
|
|
).fsPath
|
|
await terminal.run('brew', [
|
|
'install',
|
|
'--formula',
|
|
binutilsScriptPath,
|
|
gccScriptPath
|
|
])
|
|
} else {
|
|
await terminal.run('/bin/bash', [
|
|
'-c',
|
|
'$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)'
|
|
])
|
|
requiresReboot = true
|
|
vscode.window.showInformationMessage(
|
|
'Installing the Brew tool requires a reboot. Please reboot your computer before proceeding further.'
|
|
)
|
|
}
|
|
} catch (error) {
|
|
vscode.window.showErrorMessage(
|
|
'An error occurred while installing the MIPS toolchain. Please install it manually.'
|
|
)
|
|
throw error
|
|
}
|
|
break
|
|
default:
|
|
vscode.window.showErrorMessage(
|
|
'Your platform is not supported by this extension. Please install the MIPS toolchain manually.'
|
|
)
|
|
throw new Error('Unsupported platform')
|
|
}
|
|
}
|
|
|
|
async function installGDB () {
|
|
switch (process.platform) {
|
|
case 'win32':
|
|
try {
|
|
if (!(await checkInstalled('mips'))) {
|
|
await installMips()
|
|
} else {
|
|
if (win32MipsToolsInstalling) return
|
|
win32MipsToolsInstalling = true
|
|
await terminal.run('mips', ['install', mipsVersion])
|
|
}
|
|
} catch (error) {
|
|
vscode.window.showErrorMessage(
|
|
'An error occurred while installing GDB Multiarch. Please install it manually.'
|
|
)
|
|
throw error
|
|
}
|
|
break
|
|
case 'linux':
|
|
try {
|
|
if (await checkInstalled('apt')) {
|
|
await terminal.run('sudo', ['apt', 'install', 'gdb-multiarch'], {
|
|
message: 'Installing GDB Multiarch requires root privileges.'
|
|
})
|
|
} else if (await checkInstalled('trizen')) {
|
|
await terminal.run('trizen', ['-S', 'gdb-multiarch'])
|
|
} else if (await checkInstalled('brew')) {
|
|
await terminal.run('brew', ['install', 'gdb-multiarch'])
|
|
} else {
|
|
vscode.window.showErrorMessage(
|
|
'Your Linux distribution is not supported. You need to install the MIPS toolchain manually. Alternatively, you can install linuxbrew, and refresh this panel.'
|
|
)
|
|
throw new Error('Unsupported platform')
|
|
}
|
|
} catch (error) {
|
|
vscode.window.showErrorMessage(
|
|
'An error occurred while installing GDB Multiarch. Please install it manually.'
|
|
)
|
|
throw error
|
|
}
|
|
break
|
|
case 'darwin':
|
|
try {
|
|
if (await checkInstalled('brew')) {
|
|
await terminal.run('brew', ['install', 'gdb'])
|
|
} else {
|
|
await terminal.run('/bin/bash', [
|
|
'-c',
|
|
'$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)'
|
|
])
|
|
requiresReboot = true
|
|
vscode.window.showInformationMessage(
|
|
'Installing the Brew tool requires a reboot. Please reboot your computer before proceeding further.'
|
|
)
|
|
}
|
|
} catch (error) {
|
|
vscode.window.showErrorMessage(
|
|
'An error occurred while installing GDB Multiarch. Please install it manually. Alternatively, you can install linuxbrew, and refresh this panel.'
|
|
)
|
|
throw error
|
|
}
|
|
break
|
|
default:
|
|
vscode.window.showErrorMessage(
|
|
'Your platform is not supported by this extension. Please install GDB Multiarch manually.'
|
|
)
|
|
throw new Error('Unsupported platform')
|
|
}
|
|
}
|
|
|
|
async function installMake () {
|
|
switch (process.platform) {
|
|
case 'win32':
|
|
try {
|
|
if (!(await checkInstalled('mips'))) {
|
|
await installMips()
|
|
} else {
|
|
if (win32MipsToolsInstalling) return
|
|
win32MipsToolsInstalling = true
|
|
await terminal.run('mips', ['install', mipsVersion])
|
|
}
|
|
} catch (error) {
|
|
vscode.window.showErrorMessage(
|
|
'An error occurred while installing GNU Make. Please install it manually.'
|
|
)
|
|
throw error
|
|
}
|
|
break
|
|
case 'linux':
|
|
try {
|
|
if (await checkInstalled('apt')) {
|
|
await terminal.run('sudo', ['apt', 'install', 'build-essential'], {
|
|
message: 'Installing GNU Make requires root privileges.'
|
|
})
|
|
} else {
|
|
vscode.window.showErrorMessage(
|
|
'Your Linux distribution is not supported. You need to install the MIPS toolchain manually.'
|
|
)
|
|
throw new Error('Unsupported platform')
|
|
}
|
|
} catch (error) {
|
|
vscode.window.showErrorMessage(
|
|
'An error occurred while installing GNU Make. Please install it manually.'
|
|
)
|
|
throw error
|
|
}
|
|
break
|
|
default:
|
|
vscode.window.showErrorMessage(
|
|
'Your platform is not supported by this extension. Please install GNU Make manually.'
|
|
)
|
|
throw new Error('Unsupported platform')
|
|
}
|
|
}
|
|
|
|
async function installCMake () {
|
|
switch (process.platform) {
|
|
case 'win32':
|
|
const release = await octokit.rest.repos.getLatestRelease({
|
|
owner: 'Kitware',
|
|
repo: 'CMake'
|
|
})
|
|
const asset = release.data.assets.find((asset) => {
|
|
return /^cmake-.*-windows-x86_64\.msi/.test(asset.name)
|
|
})
|
|
if (!asset) {
|
|
vscode.window.showErrorMessage(
|
|
'Could not find the latest CMake release. Please install it manually.'
|
|
)
|
|
return
|
|
}
|
|
const filename = path.join(
|
|
os.tmpdir(),
|
|
asset.browser_download_url.split('/').pop()
|
|
)
|
|
await downloader.downloadFile(asset.browser_download_url, filename)
|
|
await execFile('start', [filename])
|
|
requiresReboot = true
|
|
break
|
|
case 'linux':
|
|
try {
|
|
if (await checkInstalled('apt')) {
|
|
await terminal.run('sudo', ['apt', 'install', 'cmake'], {
|
|
message: 'Installing CMake requires root privileges.'
|
|
})
|
|
} else if (await checkInstalled('trizen')) {
|
|
await terminal.run('trizen', ['-S', 'cmake'])
|
|
} else if (await checkInstalled('brew')) {
|
|
await terminal.run('brew', ['install', 'cmake'])
|
|
} else {
|
|
vscode.window.showErrorMessage(
|
|
'Your Linux distribution is not supported. You need to install CMake manually. Alternatively, you can install linuxbrew, and refresh this panel.'
|
|
)
|
|
throw new Error('Unsupported platform')
|
|
}
|
|
} catch (error) {
|
|
vscode.window.showErrorMessage(
|
|
'An error occurred while installing CMake. Please install it manually.'
|
|
)
|
|
throw error
|
|
}
|
|
break
|
|
case 'darwin':
|
|
try {
|
|
if (await checkInstalled('brew')) {
|
|
await terminal.run('brew', ['install', 'cmake'])
|
|
} else {
|
|
await terminal.run('/bin/bash', [
|
|
'-c',
|
|
'$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)'
|
|
])
|
|
requiresReboot = true
|
|
vscode.window.showInformationMessage(
|
|
'Installing the Brew tool requires a reboot. Please reboot your computer before proceeding further.'
|
|
)
|
|
}
|
|
} catch (error) {
|
|
vscode.window.showErrorMessage(
|
|
'An error occurred while installing CMake. Please install it manually. Alternatively, you can install linuxbrew, and refresh this panel.'
|
|
)
|
|
throw error
|
|
}
|
|
break
|
|
default:
|
|
vscode.window.showErrorMessage(
|
|
'Your platform is not supported by this extension. Please install CMake manually.'
|
|
)
|
|
throw new Error('Unsupported platform')
|
|
}
|
|
}
|
|
|
|
async function installGit () {
|
|
switch (process.platform) {
|
|
case 'win32': {
|
|
const release = await octokit.rest.repos.getLatestRelease({
|
|
owner: 'git-for-windows',
|
|
repo: 'git'
|
|
})
|
|
const asset = release.data.assets.find((asset) => {
|
|
return /^Git-.*-64-bit\.exe/.test(asset.name)
|
|
})
|
|
if (!asset) {
|
|
vscode.window.showErrorMessage(
|
|
'Could not find the latest Git for Windows release. Please install it manually.'
|
|
)
|
|
return
|
|
}
|
|
const filename = path.join(
|
|
os.tmpdir(),
|
|
asset.browser_download_url.split('/').pop()
|
|
)
|
|
await downloader.downloadFile(asset.browser_download_url, filename)
|
|
await execFile(filename)
|
|
requiresReboot = true
|
|
break
|
|
}
|
|
case 'linux':
|
|
if (await checkInstalled('apt')) {
|
|
return terminal.run('sudo', ['apt', 'install', 'git'], {
|
|
message: 'Installing Git requires root privileges.'
|
|
})
|
|
}
|
|
// eslint-disable-next-line no-fallthrough -- intentional
|
|
default:
|
|
return vscode.env.openExternal(
|
|
vscode.Uri.parse('https://git-scm.com/downloads')
|
|
)
|
|
}
|
|
}
|
|
|
|
async function installPython () {
|
|
switch (process.platform) {
|
|
case 'win32':
|
|
const tags = await octokit.rest.repos.listTags({
|
|
owner: 'python',
|
|
repo: 'cpython'
|
|
})
|
|
let latestVersion = [3, 12, 0]
|
|
for (const release of tags.data) {
|
|
const match = /v(3)\.([0-9]+)\.([0-9]+)$/.exec(release.name)
|
|
if (!match) {
|
|
continue
|
|
}
|
|
const version = match.slice(1).map((value) => parseInt(value))
|
|
if (version > latestVersion) {
|
|
latestVersion = version
|
|
}
|
|
}
|
|
const versionStr = latestVersion.join('.')
|
|
const url = `https://python.org/ftp/python/${versionStr}/python-${versionStr}-amd64.exe`
|
|
const filename = path.join(
|
|
os.tmpdir(),
|
|
url.split('/').pop()
|
|
)
|
|
await downloader.downloadFile(url, filename)
|
|
await execFile(filename)
|
|
requiresReboot = true
|
|
break
|
|
case 'linux':
|
|
try {
|
|
if (await checkInstalled('apt')) {
|
|
await terminal.run('sudo', ['apt', 'install', 'python3'], {
|
|
message: 'Installing Python requires root privileges.'
|
|
})
|
|
} else if (await checkInstalled('brew')) {
|
|
await terminal.run('brew', ['install', 'python@3.12'])
|
|
} else {
|
|
vscode.window.showErrorMessage(
|
|
'Your Linux distribution is not supported. You need to install Python manually. Alternatively, you can install linuxbrew, and refresh this panel.'
|
|
)
|
|
throw new Error('Unsupported platform')
|
|
}
|
|
} catch (error) {
|
|
vscode.window.showErrorMessage(
|
|
'An error occurred while installing Python. Please install it manually. Alternatively, you can install linuxbrew, and refresh this panel.'
|
|
)
|
|
throw error
|
|
}
|
|
break
|
|
default:
|
|
vscode.window.showErrorMessage(
|
|
'Your platform is not supported by this extension. Please install Python manually.'
|
|
)
|
|
throw new Error('Unsupported platform')
|
|
}
|
|
}
|
|
|
|
async function checkPython () {
|
|
switch (process.platform) {
|
|
case 'win32':
|
|
/*
|
|
* We cannot simply run 'python --version' here as Windows ships by
|
|
* default with fake (zero-byte) 'python' and 'python3' executables in its
|
|
* PATH. These files are actually links to UWP apps, implemented using a
|
|
* specific NTFS reparse tag. If Python is installed from the Microsoft
|
|
* Store they behave as if they were symlinks to the actual executables;
|
|
* if not, however, attempting to run them will result in the store
|
|
* popping up and prompting the user to install Python.
|
|
*
|
|
* A kludge is thus needed here in order to prevent this from happening.
|
|
* We'll first check for any UWP Python installations, then search PATH
|
|
* manually and skip the fake binaries if none was found. This ensures
|
|
* both UWP and non-UWP installs will be detected somewhat reliably.
|
|
*
|
|
* IMPORTANT: this assumes that the project's build system will also be
|
|
* able to detect and ignore the fake executables (rather than e.g.
|
|
* blindly executing 'python'). This is currently the case for the
|
|
* CMake-based templates.
|
|
*/
|
|
let hasUWPPython
|
|
try {
|
|
const result = await execFile('powershell', [
|
|
'-c',
|
|
'Get-AppxPackage -Name PythonSoftwareFoundation.Python.*'
|
|
])
|
|
hasUWPPython = (result.stdout.trim() !== '')
|
|
} catch (error) {
|
|
hasUWPPython = false
|
|
}
|
|
for (const command of ['python3', 'python', 'py']) {
|
|
const matches = await which(command, { all: true })
|
|
for (const fullPath of matches) {
|
|
const stats = await fs.stat(fullPath)
|
|
if (!stats.size && !hasUWPPython) {
|
|
continue
|
|
}
|
|
try {
|
|
await execFile(fullPath, ['--version'])
|
|
} catch (error) {
|
|
continue
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
default:
|
|
return checkCommands(['python3', 'python'], ['--version'])
|
|
}
|
|
}
|
|
|
|
function unpackPsyq (destination) {
|
|
const filename = vscode.Uri.joinPath(
|
|
globalStorageUri,
|
|
tools.psyq.filename
|
|
).fsPath
|
|
|
|
return fs
|
|
.createReadStream(filename)
|
|
.pipe(unzipper.Parse())
|
|
.on('entry', function (entry) {
|
|
const fragments = entry.path.split('/')
|
|
fragments.shift()
|
|
const outputPath = path.join(destination, ...fragments)
|
|
if (entry.type === 'Directory') {
|
|
fs.mkdirSync(outputPath, { recursive: true })
|
|
entry.autodrain()
|
|
} else {
|
|
entry.pipe(fs.createWriteStream(outputPath))
|
|
}
|
|
})
|
|
.promise()
|
|
}
|
|
|
|
const tools = {
|
|
mips: {
|
|
type: 'internal',
|
|
install: installMips,
|
|
check: () => checkCommands(['mips'], ['--version'])
|
|
},
|
|
apt: {
|
|
type: 'internal',
|
|
check: () => checkCommands(['apt-get'], ['--version'])
|
|
},
|
|
trizen: {
|
|
type: 'internal',
|
|
check: () => checkCommands(['trizen'], ['--version'])
|
|
},
|
|
brew: {
|
|
type: 'internal',
|
|
install: 'https://brew.sh/',
|
|
check: () => checkCommands(['brew'], ['--version'])
|
|
},
|
|
toolchain: {
|
|
type: 'package',
|
|
name: 'MIPS Toolchain',
|
|
description: 'The toolchain used to compile code for the PlayStation 1',
|
|
homepage: 'https://gcc.gnu.org/',
|
|
install: installToolchain,
|
|
check: () => checkCommands(
|
|
['mipsel-none-elf-g++', 'mipsel-linux-gnu-g++'],
|
|
['--version']
|
|
)
|
|
},
|
|
gdb: {
|
|
type: 'package',
|
|
name: 'GDB Multiarch',
|
|
description: 'The tool to debug code for the PlayStation 1',
|
|
homepage: 'https://www.sourceware.org/gdb/',
|
|
install: installGDB,
|
|
check: () => checkCommands(
|
|
[(process.platform === 'darwin') ? 'gdb' : 'gdb-multiarch'],
|
|
['--version']
|
|
)
|
|
},
|
|
make: {
|
|
type: 'package',
|
|
name: 'GNU Make',
|
|
description: 'Build code and various targets with this tool',
|
|
homepage: 'https://www.gnu.org/software/make/',
|
|
install: installMake,
|
|
check: () => checkCommands(['make'], ['--version'])
|
|
},
|
|
cmake: {
|
|
type: 'package',
|
|
name: 'CMake',
|
|
description: 'A more advanced building tool for projects that require it',
|
|
homepage: 'https://cmake.org/',
|
|
install: installCMake,
|
|
check: () => checkCommands(['cmake'], ['--version'])
|
|
},
|
|
git: {
|
|
type: 'package',
|
|
name: 'Git',
|
|
description:
|
|
'Tool to maintain your code, and initialize your project templates',
|
|
homepage: 'https://git-scm.com/',
|
|
install: installGit,
|
|
check: () => checkCommands(['git'], ['--version'])
|
|
},
|
|
python: {
|
|
type: 'package',
|
|
name: 'Python',
|
|
description:
|
|
'Python language runtime, required to run some project templates\' scripts',
|
|
homepage: 'https://python.org/',
|
|
install: installPython,
|
|
check: checkPython
|
|
},
|
|
clangd: {
|
|
type: 'extension',
|
|
name: 'clangd',
|
|
description:
|
|
'A VSCode extension providing code completion within VSCode, and other features',
|
|
homepage:
|
|
'https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd',
|
|
id: 'llvm-vs-code-extensions.vscode-clangd'
|
|
},
|
|
cmaketools: {
|
|
type: 'extension',
|
|
name: 'CMake Tools extension',
|
|
description:
|
|
'A VSCode extension providing support for configuring and building CMake-based projects',
|
|
homepage:
|
|
'https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools',
|
|
id: 'ms-vscode.cmake-tools'
|
|
},
|
|
debugger: {
|
|
type: 'extension',
|
|
name: 'Debugger connector',
|
|
description:
|
|
'A VSCode extension to connect to the PlayStation 1 or an emulator, and debug your code',
|
|
homepage:
|
|
'https://marketplace.visualstudio.com/items?itemName=webfreak.debug',
|
|
id: 'webfreak.debug'
|
|
},
|
|
mipsassembly: {
|
|
type: 'extension',
|
|
name: 'MIPS assembly extension',
|
|
description:
|
|
'A VSCode extension that provides syntax highlighting for MIPS assembly code',
|
|
homepage:
|
|
'https://marketplace.visualstudio.com/items?itemName=kdarkhan.mips',
|
|
id: 'kdarkhan.mips'
|
|
},
|
|
psyq: {
|
|
type: 'archive',
|
|
name: 'Psy-Q SDK',
|
|
description:
|
|
'The original SDK made by Sony used to develop code for the PlayStation 1. Please note that you are not going to receive a license to use this SDK from Sony by downloading it, and so using it should be at your own risks.',
|
|
homepage: 'https://psx.arthus.net/sdk/Psy-Q/',
|
|
filename: 'psyq-4_7-converted-light.zip',
|
|
url: 'https://psx.arthus.net/sdk/Psy-Q/psyq-4_7-converted-light.zip',
|
|
unpack: unpackPsyq
|
|
},
|
|
redux: {
|
|
type: 'archive',
|
|
name: 'PCSX-Redux',
|
|
description:
|
|
'A PlayStation 1 emulator focusing on development features, enabling you to debug your code easily.',
|
|
homepage: 'https://pcsx-redux.consoledev.net/',
|
|
launch: pcsxRedux.launch,
|
|
install: pcsxRedux.install,
|
|
check: pcsxRedux.check
|
|
}
|
|
}
|
|
|
|
function checkLocalFile (filename) {
|
|
return new Promise((resolve) => {
|
|
filename = vscode.Uri.joinPath(globalStorageUri, filename).fsPath
|
|
fs.access(filename, fs.constants.F_OK, (err) => {
|
|
resolve(!err)
|
|
})
|
|
})
|
|
}
|
|
|
|
exports.refreshAll = async () => {
|
|
for (const [, tool] of Object.entries(tools)) {
|
|
if (tool.check) {
|
|
try {
|
|
tool.installed = await tool.check()
|
|
} catch (error) {
|
|
tool.installed = false
|
|
}
|
|
} else if (tool.type === 'extension') {
|
|
tool.installed = vscode.extensions.getExtension(tool.id) !== undefined
|
|
} else if (tool.type === 'archive') {
|
|
tool.installed = await checkLocalFile(tool.filename)
|
|
}
|
|
}
|
|
return tools
|
|
}
|
|
|
|
exports.list = tools
|
|
|
|
exports.setExtensionUri = (uri) => {
|
|
extensionUri = uri
|
|
}
|
|
|
|
exports.setGlobalStorageUri = (uri) => {
|
|
globalStorageUri = uri
|
|
}
|
|
|
|
exports.install = async (toInstall, force) => {
|
|
if (requiresReboot) {
|
|
return true
|
|
}
|
|
for (const tool of toInstall) {
|
|
if (!force && (await checkInstalled(tool))) continue
|
|
if (tools[tool].install) {
|
|
if (typeof tools[tool].install === 'string') {
|
|
vscode.env.openExternal(vscode.Uri.parse(tools[tool].install))
|
|
} else {
|
|
await tools[tool].install(force)
|
|
}
|
|
} else if (tools[tool].type === 'extension') {
|
|
const extensionId = tools[tool].id
|
|
await vscode.commands.executeCommand('extension.open', extensionId)
|
|
} else if (tools[tool].type === 'archive') {
|
|
await downloader.downloadFile(
|
|
tools[tool].url,
|
|
vscode.Uri.joinPath(globalStorageUri, tools[tool].filename).fsPath
|
|
)
|
|
}
|
|
}
|
|
win32MipsToolsInstalling = false
|
|
return requiresReboot
|
|
}
|
|
|
|
exports.maybeInstall = async (toInstall) => {
|
|
const installed = await checkInstalled(toInstall)
|
|
if (!installed && !requiresReboot) {
|
|
const ret = exports.install([toInstall])
|
|
win32MipsToolsInstalling = false
|
|
return ret
|
|
}
|
|
return requiresReboot
|
|
}
|