From b38a9ded5ea60f26a56b1f58f8cb94428b4250a3 Mon Sep 17 00:00:00 2001 From: Manuel <53863351+ManuelHentschel@users.noreply.github.com> Date: Sun, 8 Sep 2024 18:36:19 +0200 Subject: [PATCH] Change package installation functions --- R/install.R | 70 +++++++++++++++++++++++++++++++++++++++--- R/install_or_update.R | 9 ++++++ R/remove.R | 3 ++ package.json | 14 +++++++-- readme.md | 39 +++++++++++++---------- src/extension.ts | 6 ++-- src/installRPackage.ts | 19 ++++++++++-- 7 files changed, 132 insertions(+), 28 deletions(-) create mode 100644 R/install_or_update.R create mode 100644 R/remove.R diff --git a/R/install.R b/R/install.R index ee47928..4d9883b 100644 --- a/R/install.R +++ b/R/install.R @@ -1,9 +1,69 @@ -repos <- getOption("repos") -if (is.null(repos) || identical(repos, c(CRAN = "@CRAN@"))) { - options(repos = c(CRAN = "https://cloud.r-project.org/")) -} +# This script tries to install the vscDebugger package from various sources. +# Uses lots of `try()` calls to have the highest chance of success. +# Intended for new users, who are not familiar with R package installation. + + +## Repos setup ("@CRAN@" in options might need to be replaced by a default mirror URL) +repos <- getOption("repos", "https://cloud.r-project.org/") +repos <- gsub("@CRAN@", "https://cloud.r-project.org/", repos) +options(repos = repos) + + +## Install dependencies +cat('Installing dependencies: jsonlite, R6...\n') install.packages(c("jsonlite", "R6")) + + +## Install vscDebugger +# Exit if package already installed +if('vscDebugger' %in% rownames(installed.packages())) { + cat('\nPackage vscDebugger already installed. Remove it manually to force reinstall.\n') + quit(save = 'no', status = 1) +} + +# Helper function to exit after successful installation +exit_if_ok <- function(...) { + if('vscDebugger' %in% rownames(installed.packages())) { + cat('\nPackage vscDebugger installed successfully.\n', ...) + quit(save = 'no', status = 0) + } +} + + +# Try to install from r-universe.dev +cat('\nInstalling vscDebugger from r-universe.dev...\n') +try(install.packages("vscDebugger", repos = "https://manuelhentschel.r-universe.dev")) +exit_if_ok() +warning('Installing from r-universe.dev failed!') + + +# Install remotes package if not already installed +remotes_installed <- function() ('remotes' %in% rownames(installed.packages())) +if(!remotes_installed()) { + cat('Package `remotes` not installed, trying to install it...\n') + try(install.packages("remotes")) +} + +# Try remotes package if available +if(remotes_installed()) { + cat('\nInstalling vscDebugger from GitHub...\n') + try(remotes::install_github("ManuelHentschel/vscDebugger")) + exit_if_ok() + warning('Installing from GitHub failed!') +} else { + warning('Installing package `remotes` failed! Skipping installation from GitHub.\n') +} + + +# Try from GitHub action artifact +cat('\nInstalling vscDebugger from GitHub action artifact...\n') url <- commandArgs(trailingOnly = TRUE)[[1]] -install.packages(url, repos = NULL) +try(install.packages(url, repos = NULL)) +exit_if_ok('A newer version might be available on GitHub.\n') +warning('Installing from GitHub action artifact failed!') + + +# Only reached if all installation attempts failed +stop('Installation failed. Make sure the pacakge is not loaded in any R session, or try installing manually.') diff --git a/R/install_or_update.R b/R/install_or_update.R new file mode 100644 index 0000000..61f40db --- /dev/null +++ b/R/install_or_update.R @@ -0,0 +1,9 @@ + +# Try to install or update from r-universe.dev +options(warn=2) + +repos <- getOption("repos", "https://cloud.r-project.org/") +repos <- gsub("@CRAN@", "https://cloud.r-project.org/", repos) +repos <- c("https://manuelhentschel.r-universe.dev", repos) + +install.packages("vscDebugger", repos = repos) diff --git a/R/remove.R b/R/remove.R new file mode 100644 index 0000000..9232832 --- /dev/null +++ b/R/remove.R @@ -0,0 +1,3 @@ + +# Remove package +remove.packages('vscDebugger') diff --git a/package.json b/package.json index b15b2b2..80c82e5 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,18 @@ "contributes": { "commands": [ { - "command": "r.debugger.updateRPackage", - "title": "Update or install the required R Package", + "command": "r.debugger.installOrUpdateRPackage", + "title": "Install or update the required R Package (quick)", + "category": "R Debugger" + }, + { + "command": "r.debugger.installRPackage", + "title": "Install the required R Package (slow, multiple sources)", + "category": "R Debugger" + }, + { + "command": "r.debugger.removeRPackage", + "title": "Remove the required R Package", "category": "R Debugger" }, { diff --git a/readme.md b/readme.md index 03e3f32..ed2a20b 100644 --- a/readme.md +++ b/readme.md @@ -27,24 +27,31 @@ For many variables it is also possible to assign a new value to the variable or ## Installation The latest version of the VS Code extension can be installed from the [marketplace](https://marketplace.visualstudio.com/items?itemName=RDebugger.r-debugger). -After installing the extension, the R package can be installed using the command -`r.debugger.updateRPackage`. -If this does not work, you can find the source code and compiled binaries on the +After installing the extension, the R package can be installed or updated using the command +`r.debugger.installOrUpdateRPackage`. +If your R path is neither in the Windows registry nor the `PATH` environment variable, make sure to provide a valid path to the R executable in the setting `r.rpath.xxx`. + +If the package installation does not work, +the command `r.debugger.installRPackage` will attempt to install from +a release on [r-universe.dev](https://manuelhentschel.r-universe.dev), +the source code on [GitHub](https://GitHub.com/ManuelHentschel/vscDebugger), +and a [GitHub Release](https://github.com/ManuelHentschel/VSCode-R-Debugger/releases) +(in that order). +You can also install the package manually using +```r +# OPTION 1: From r-universe.dev: +install.packages("vscDebugger", repos = "https://manuelhentschel.r-universe.dev") + +# OPTION 2: From source code on GitHub: +remotes::install_github("ManuelHentschel/vscDebugger") +``` +or from artifacts on the [releases site](https://github.com/ManuelHentschel/VSCode-R-Debugger/releases). -The provided packages were built using the latest R release and might be incompatible with older R versions. -In these cases it is necessary to build the package from code. - -If you want to install a development version, the VS Code extension can be installed from the .vsix-files found -[here](https://github.com/ManuelHentschel/VSCode-R-Debugger/actions?query=workflow%3Amain). -To download the correct file, filter the commits by branch, select the latest commit, -and download the file `r-debugger.vsix` under the caption "Artifacts". -To install the latest development version of the required R-package from GitHub, run -`devtools::install_github("ManuelHentschel/vscDebugger")` -or install from the artifacts found -[here](https://github.com/ManuelHentschel/vscDebugger/actions). -If your R path is neither in the Windows registry nor the `PATH` environment variable, make sure to provide a valid path to the R executable in `r.rpath.xxx`. +If you want to install a development version of the extension, +it can be installed from the .vsix-files found in the artifacts of the +[GitHub Actions Workflows](https://github.com/ManuelHentschel/VSCode-R-Debugger/actions?query=workflow%3Amain). ## Using the Debugger ### Launch Mode @@ -119,7 +126,7 @@ to compile the binaries and again with to retain the source information. The packages that are being debugged then need to be specified in the launch config as follows: -```json +```jsonc "debuggedPackages": ["MyPackage"], ... ``` diff --git a/src/extension.ts b/src/extension.ts index ed81cc0..9bde9a1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,7 +1,7 @@ import * as vscode from 'vscode'; -import { updateRPackage } from './installRPackage'; +import { installRPackage } from './installRPackage'; import { trackTerminals, TerminalHandler } from './terminals'; import { RExtension, HelpPanel } from './rExtensionApi'; @@ -64,7 +64,9 @@ export async function activate(context: vscode.ExtensionContext): Promise } context.subscriptions.push( - vscode.commands.registerCommand('r.debugger.updateRPackage', () => updateRPackage(context.extensionPath)), + vscode.commands.registerCommand('r.debugger.installOrUpdateRPackage', () => installRPackage(context.extensionPath, 'installOrUpdate')), + vscode.commands.registerCommand('r.debugger.installRPackage', () => installRPackage(context.extensionPath, 'install')), + vscode.commands.registerCommand('r.debugger.removeRPackage', () => installRPackage(context.extensionPath, 'remove')), vscode.commands.registerCommand('r.debugger.showDataViewer', (arg: DebugWindowCommandArg) => { showDataViewer(arg); }) diff --git a/src/installRPackage.ts b/src/installRPackage.ts index 5d599b1..e89a650 100644 --- a/src/installRPackage.ts +++ b/src/installRPackage.ts @@ -1,7 +1,7 @@ import { getRDownloadLink, getRStartupArguments, config, getRequiredRPackageVersion } from './utils'; import * as vscode from 'vscode'; -import { join } from 'path'; +import * as path from 'path'; import semver = require('semver'); export interface PackageVersionInfo { @@ -13,18 +13,31 @@ export interface PackageVersionInfo { type VersionCheckLevel = 'none'|'required'|'recommended'; +type InstallType = 'install'|'installOrUpdate'|'remove'; -export async function updateRPackage(extensionPath: string): Promise { + +export async function installRPackage(extensionPath: string, installType: InstallType): Promise { const url = getRDownloadLink(); const rPath = (await getRStartupArguments()).path.replace(/^"(.*)"$/, '$1'); const taskDefinition: vscode.TaskDefinition = { type: 'process' }; + let filename: string; + if(installType==='installOrUpdate'){ + filename = 'install_or_update.R'; + } else if(installType==='remove'){ + filename = 'remove.R'; + } else { + filename = 'install.R'; + } + filename = `${path.join(extensionPath, 'R', filename)}`; + const args = [ '--no-restore', + '--no-save', '--quiet', '-f', - `${join(extensionPath, 'R', 'install.R')}`, + filename, '--args', `${url}` ];