Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@
^\.jupyter$
^[.]?air[.]toml$
^\.vscode$
^\.devcontainer$
^\.sync$
^\.claude$
^\.devcontainer$
20 changes: 20 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "rJavaEnv Dev Container",
"image": "mcr.microsoft.com/devcontainers/r:latest",
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {}
},
"customizations": {
"vscode": {
"extensions": [
"quarto.quarto",
"Posit.air-vscode",
"REditorSupport.r"
]
}
},
"postCreateCommand": "bash .devcontainer/setup.sh",
"remoteEnv": {
"PATH": "${containerEnv:PATH}:/home/vscode/.local/bin"
}
}
17 changes: 17 additions & 0 deletions .devcontainer/setup.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env Rscript

# Ensure remotes is installed
if (!requireNamespace("remotes", quietly = TRUE)) {
install.packages("remotes")
}

# Get dependencies from DESCRIPTION in the current directory
deps <- remotes::dev_package_deps(dependencies = TRUE)

# Filter out rJava to ensure no Java is installed
# deps is a data.frame with class "package_deps"
deps <- deps[deps$package != "rJava", ]

# Install/Update the selected packages
# The update() method for package_deps respects version requirements
remotes::update(deps, upgrade = "always")
48 changes: 48 additions & 0 deletions .devcontainer/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/bash
set -e

# Configuration
AIR_VERSION="0.8.0"
INSTALL_DIR="$HOME/.local/bin"
mkdir -p "$INSTALL_DIR"

# Detect Architecture
ARCH=$(uname -m)
if [ "$ARCH" = "x86_64" ]; then
AIR_ARCH="x86_64"
elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
AIR_ARCH="aarch64"
else
echo "Unsupported architecture: $ARCH"
exit 1
fi

PLATFORM="unknown-linux-gnu"
FILENAME="air-${AIR_ARCH}-${PLATFORM}.tar.gz"
URL="https://github.com/posit-dev/air/releases/download/${AIR_VERSION}/${FILENAME}"

echo "Installing Posit Air CLI version ${AIR_VERSION} for ${AIR_ARCH}..."

# Download and install
# We use a temporary directory to ensure clean cleanup
TMP_DIR=$(mktemp -d)
curl -LsSf "$URL" -o "${TMP_DIR}/${FILENAME}"
tar -xzf "${TMP_DIR}/${FILENAME}" -C "$TMP_DIR"
mv "${TMP_DIR}/air" "$INSTALL_DIR/air"
rm -rf "$TMP_DIR"

# Ensure air is on PATH for the remainder of this setup script.
export PATH="$INSTALL_DIR:$PATH"

# Verify Air CLI installation
if ! command -v air &> /dev/null; then
echo "Error: Air CLI failed to install or is not in PATH."
exit 1
fi
echo "Air CLI installed successfully: $(air --version)"

# Install R dependencies
echo "Installing R dependencies (excluding rJava)..."
Rscript .devcontainer/setup.R

echo "Setup complete!"
14 changes: 7 additions & 7 deletions R/global_params.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,23 @@ global_quiet_param <- function(quiet) {
#' Documentation template for rJava path-locking behavior.
#'
#' @section rJava Path-Locking:
#' **Important for rJava Users**: This function sets environment variables
#' (JAVA_HOME, PATH) that affect both command-line Java tools and rJava initialization.
#' However, due to rJava's path-locking behavior when \code{\link[rJava]{.jinit}} is called
#' **Important for \emph{rJava} Users**: This function sets environment variables
#' (JAVA_HOME, PATH) that affect both command-line Java tools and \emph{rJava} initialization.
#' However, due to \emph{rJava}'s path-locking behavior when \code{\link[rJava]{.jinit}} is called
#' (see \url{https://github.com/s-u/rJava/issues/25}, \url{https://github.com/s-u/rJava/issues/249}, and \url{https://github.com/s-u/rJava/issues/334}),
#' this function must be called **BEFORE** \code{\link[rJava]{.jinit}} is invoked. Once \code{\link[rJava]{.jinit}}
#' initializes, the Java version is locked for that R session and cannot be changed without restarting R.
#'
#' \code{\link[rJava]{.jinit}} is invoked (and Java locked) when you:
#' \itemize{
#' \item Explicitly call \code{library(rJava)}
#' \item Load any package that imports rJava (which auto-loads it as a dependency)
#' \item Load any package that imports \emph{rJava} (which auto-loads it as a dependency)
#' \item Even just use IDE autocomplete with \code{rJava::} (this triggers initialization!)
#' \item Call any rJava-dependent function
#' \item Call any \emph{rJava}-dependent function
#' }
#'
#' Once any of these happen, the Java version used by rJava for that session is locked in.
#' For command-line Java tools that don't use rJava, this function can be called at any
#' Once any of these happen, the Java version used by \emph{rJava} for that session is locked in.
#' For command-line Java tools that don't use \emph{rJava}, this function can be called at any
#' time to switch Java versions for subsequent system calls.
#'
#' @keywords internal
Expand Down
1 change: 1 addition & 0 deletions R/internal_utilities.R
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ java_check_current_rjava_version <- function() {
#' @param temp_dir The directory where files were extracted.
#' @return The path to the first non-hidden directory found.
#' @keywords internal
#' @noRd
._find_extracted_dir <- function(temp_dir) {
# Ignore hidden files like .DS_Store or AppleDouble files (._)
all_files <- list.files(temp_dir, full.names = TRUE)
Expand Down
19 changes: 18 additions & 1 deletion R/java_install.R
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,24 @@ java_install <- function(
arch <- parts[vapply(parts, function(x) x %in% architectures, logical(1))][1]
platform <- parts[vapply(parts, function(x) x %in% platforms, logical(1))][1]

# Create a symlink in the project directory (new structure with distribution/backend)
# Validate detection results
if (is.na(version)) {
cli::cli_abort(
"Unable to detect Java version from filename {.file {filename}}. Please ensure the filename contains a valid version number."
)
}
if (is.na(arch)) {
cli::cli_abort(
"Unable to detect architecture from filename {.file {filename}}. Expected one of: {.val {architectures}}"
)
}
if (is.na(platform)) {
cli::cli_abort(
"Unable to detect platform from filename {.file {filename}}. Expected one of: {.val {platforms}}"
)
}
Comment thread
e-kotov marked this conversation as resolved.
Outdated

# Create a symlink in the project directory
project_version_path <- file.path(
project_path,
"rjavaenv",
Expand Down
14 changes: 7 additions & 7 deletions man/java_ensure.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions man/java_env_set.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions man/rjava_path_locking_note.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions man/use_java.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions tests/testthat/test-java_install-mocked.R
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,10 @@ test_that("java_install falls back to file.copy when symlink fails on Unix", {
expect_equal(copy_calls, 1)
})
test_that("java_install respects autoset_java_env = FALSE", {
skip_on_os("windows") # Uses Linux filename, not applicable on Windows
local_proj_path <- withr::local_tempdir()
# The path string itself doesn't matter, as we will mock the function that uses it.
fake_distrib_path <- "any/fake/path/jdk.tar.gz"
# Use a valid-looking filename that can be properly parsed
fake_distrib_path <- "any/fake/path/amazon-corretto-21-x64-linux-jdk.tar.gz"

# --- THE FIX ---
# Add a local mock for java_unpack(). This prevents the real function
Expand Down
3 changes: 3 additions & 0 deletions tools/meta-data-update-and-submission.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ cffr::cff_write()
codemetar::write_codemeta(write_minimeta = T)
# urlchecker::url_check()
# devtools::check(remote = TRUE, manual = TRUE)
# devtools::check_win_oldrelease()
# devtools::check_win_release()
# devtools::check_win_devel()
# foghorn::winbuilder_queue()
# revdepcheck::revdep_check(num_workers = 4)
# devtools::submit_cran()

Expand Down
Loading