Add reproducible R package management system
- Add renv.lock with exact package versions for reproducibility
- Add package_manager.R for automated package installation/updates
- Add extract_current_versions.R for package discovery
- Configure renv environment for team collaboration
All team members can now run source('r_app/package_manager.R') to get identical package environment
This commit is contained in:
parent
6efcc8cfec
commit
4d6439d5e0
200
r_app/extract_current_versions.R
Normal file
200
r_app/extract_current_versions.R
Normal file
|
|
@ -0,0 +1,200 @@
|
||||||
|
#' Version Extractor for SmartCane Project
|
||||||
|
#'
|
||||||
|
#' This script scans your R scripts to find all used packages and extracts
|
||||||
|
#' the currently installed versions. Use this to populate the package_manager.R
|
||||||
|
#' with your actual working versions.
|
||||||
|
#'
|
||||||
|
#' Usage:
|
||||||
|
#' source("extract_current_versions.R")
|
||||||
|
#'
|
||||||
|
#' Author: SmartCane Team
|
||||||
|
#' Date: 2025-06-24
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# PACKAGE DISCOVERY
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
#' Extract packages from R scripts
|
||||||
|
extract_packages_from_scripts <- function(script_dir = ".") {
|
||||||
|
# Find all R files
|
||||||
|
r_files <- list.files(script_dir, pattern = "\\.(R|Rmd)$", recursive = TRUE, full.names = TRUE)
|
||||||
|
|
||||||
|
packages <- c()
|
||||||
|
|
||||||
|
for (file in r_files) {
|
||||||
|
cat("Scanning:", file, "\n")
|
||||||
|
|
||||||
|
tryCatch({
|
||||||
|
content <- readLines(file, warn = FALSE)
|
||||||
|
|
||||||
|
# Find library() calls
|
||||||
|
library_matches <- regmatches(content, regexpr('library\\(["\']?([^"\'\\)]+)["\']?\\)', content))
|
||||||
|
library_packages <- gsub('library\\(["\']?([^"\'\\)]+)["\']?\\)', '\\1', library_matches)
|
||||||
|
library_packages <- library_packages[library_packages != ""]
|
||||||
|
|
||||||
|
# Find require() calls
|
||||||
|
require_matches <- regmatches(content, regexpr('require\\(["\']?([^"\'\\)]+)["\']?\\)', content))
|
||||||
|
require_packages <- gsub('require\\(["\']?([^"\'\\)]+)["\']?\\)', '\\1', require_matches)
|
||||||
|
require_packages <- require_packages[require_packages != ""]
|
||||||
|
|
||||||
|
# Find package::function calls
|
||||||
|
namespace_matches <- regmatches(content, gregexpr('[a-zA-Z][a-zA-Z0-9.]*::', content))
|
||||||
|
namespace_packages <- unique(unlist(lapply(namespace_matches, function(x) gsub('::', '', x))))
|
||||||
|
namespace_packages <- namespace_packages[namespace_packages != ""]
|
||||||
|
|
||||||
|
packages <- c(packages, library_packages, require_packages, namespace_packages)
|
||||||
|
|
||||||
|
}, error = function(e) {
|
||||||
|
cat("Error reading", file, ":", e$message, "\n")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clean and deduplicate
|
||||||
|
packages <- unique(packages)
|
||||||
|
packages <- packages[!packages %in% c("", "base", "stats", "utils", "graphics", "grDevices")]
|
||||||
|
|
||||||
|
return(sort(packages))
|
||||||
|
}
|
||||||
|
|
||||||
|
#' Get current version of installed packages
|
||||||
|
get_current_versions <- function(packages) {
|
||||||
|
versions <- list()
|
||||||
|
|
||||||
|
cat("\nChecking installed versions...\n")
|
||||||
|
cat("===============================\n")
|
||||||
|
|
||||||
|
for (pkg in packages) {
|
||||||
|
if (pkg %in% rownames(installed.packages())) {
|
||||||
|
version <- as.character(packageVersion(pkg))
|
||||||
|
versions[[pkg]] <- version
|
||||||
|
cat(sprintf("✓ %-20s %s\n", pkg, version))
|
||||||
|
} else {
|
||||||
|
cat(sprintf("✗ %-20s NOT INSTALLED\n", pkg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(versions)
|
||||||
|
}
|
||||||
|
|
||||||
|
#' Generate package manager configuration
|
||||||
|
generate_package_config <- function(versions) {
|
||||||
|
cat("\n\nGenerating REQUIRED_PACKAGES configuration...\n")
|
||||||
|
cat("=============================================\n\n")
|
||||||
|
|
||||||
|
config_lines <- c(
|
||||||
|
"# Package requirements with your current working versions",
|
||||||
|
"REQUIRED_PACKAGES <- list("
|
||||||
|
)
|
||||||
|
|
||||||
|
# Group packages by category
|
||||||
|
categories <- list(
|
||||||
|
"Core data manipulation" = c("here", "dplyr", "tidyr", "readr", "readxl", "magrittr", "lubridate", "stringr"),
|
||||||
|
"Spatial data" = c("sf", "terra", "exactextractr", "raster", "sp", "sf", "rgdal", "rgeos"),
|
||||||
|
"Visualization" = c("tmap", "ggplot2", "RColorBrewer", "viridis", "scales"),
|
||||||
|
"Statistical analysis" = c("lme4", "nlme", "mgcv", "survival", "cluster"),
|
||||||
|
"Reporting" = c("knitr", "rmarkdown", "officedown", "officer", "flextable"),
|
||||||
|
"Tidyverse" = c("tidyverse", "purrr", "forcats", "tibble"),
|
||||||
|
"Other packages" = c()
|
||||||
|
)
|
||||||
|
|
||||||
|
# Categorize packages
|
||||||
|
categorized <- list()
|
||||||
|
uncategorized <- names(versions)
|
||||||
|
|
||||||
|
for (category in names(categories)) {
|
||||||
|
cat_packages <- intersect(names(versions), categories[[category]])
|
||||||
|
if (length(cat_packages) > 0) {
|
||||||
|
categorized[[category]] <- cat_packages
|
||||||
|
uncategorized <- setdiff(uncategorized, cat_packages)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add uncategorized packages
|
||||||
|
if (length(uncategorized) > 0) {
|
||||||
|
categorized[["Other packages"]] <- uncategorized
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate config
|
||||||
|
for (category in names(categorized)) {
|
||||||
|
config_lines <- c(config_lines, paste0(" # ", category))
|
||||||
|
|
||||||
|
packages_in_cat <- categorized[[category]]
|
||||||
|
for (i in seq_along(packages_in_cat)) {
|
||||||
|
pkg <- packages_in_cat[i]
|
||||||
|
version <- versions[[pkg]]
|
||||||
|
comma <- if (i == length(packages_in_cat) && category == names(categorized)[length(categorized)]) "" else ","
|
||||||
|
|
||||||
|
# Add special comment for critical packages
|
||||||
|
comment <- ""
|
||||||
|
if (pkg == "tmap") comment <- " # CRITICAL: for tm_scale_continuous() syntax"
|
||||||
|
if (pkg == "terra") comment <- " # CRITICAL: for raster processing"
|
||||||
|
|
||||||
|
config_lines <- c(config_lines, sprintf(' "%s" = "%s"%s%s', pkg, version, comma, comment))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (category != names(categorized)[length(categorized)]) {
|
||||||
|
config_lines <- c(config_lines, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config_lines <- c(config_lines, ")")
|
||||||
|
|
||||||
|
# Print to console
|
||||||
|
cat(paste(config_lines, collapse = "\n"))
|
||||||
|
|
||||||
|
# Save to file
|
||||||
|
writeLines(config_lines, "generated_package_config.R")
|
||||||
|
cat("\n\n📁 Configuration saved to: generated_package_config.R\n")
|
||||||
|
|
||||||
|
return(config_lines)
|
||||||
|
}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# MAIN EXECUTION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
main <- function() {
|
||||||
|
cat("🔍 SmartCane Package Version Extractor\n")
|
||||||
|
cat("======================================\n\n")
|
||||||
|
|
||||||
|
# Step 1: Find all packages used in scripts
|
||||||
|
cat("Step 1: Scanning R scripts for package usage...\n")
|
||||||
|
packages <- extract_packages_from_scripts()
|
||||||
|
|
||||||
|
cat("\nFound packages:\n")
|
||||||
|
cat(paste(packages, collapse = ", "), "\n")
|
||||||
|
cat("\nTotal packages found:", length(packages), "\n")
|
||||||
|
|
||||||
|
# Step 2: Get current versions
|
||||||
|
cat("\nStep 2: Checking installed versions...\n")
|
||||||
|
versions <- get_current_versions(packages)
|
||||||
|
|
||||||
|
installed_count <- length(versions)
|
||||||
|
missing_count <- length(packages) - installed_count
|
||||||
|
|
||||||
|
cat(sprintf("\n📊 Summary: %d installed, %d missing\n", installed_count, missing_count))
|
||||||
|
|
||||||
|
if (missing_count > 0) {
|
||||||
|
missing_packages <- setdiff(packages, names(versions))
|
||||||
|
cat("\n⚠️ Missing packages:\n")
|
||||||
|
cat(paste(missing_packages, collapse = ", "), "\n")
|
||||||
|
cat("\nYou may want to install these first, then re-run this script.\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Step 3: Generate configuration
|
||||||
|
if (length(versions) > 0) {
|
||||||
|
cat("\nStep 3: Generating package manager configuration...\n")
|
||||||
|
config <- generate_package_config(versions)
|
||||||
|
|
||||||
|
cat("\n✅ Next steps:\n")
|
||||||
|
cat("1. Review generated_package_config.R\n")
|
||||||
|
cat("2. Copy the REQUIRED_PACKAGES list to package_manager.R\n")
|
||||||
|
cat("3. Adjust any versions as needed\n")
|
||||||
|
cat("4. Run package_manager.R\n")
|
||||||
|
} else {
|
||||||
|
cat("\n❌ No installed packages found. Install packages first.\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run the extraction
|
||||||
|
main()
|
||||||
315
r_app/package_manager.R
Normal file
315
r_app/package_manager.R
Normal file
|
|
@ -0,0 +1,315 @@
|
||||||
|
#' Package Manager for SmartCane Project
|
||||||
|
#'
|
||||||
|
#' This script manages R package versions across development, testing, and production environments.
|
||||||
|
#' It uses renv for reproducible environments and ensures consistent package versions.
|
||||||
|
#'
|
||||||
|
#' Usage:
|
||||||
|
#' source("package_manager.R")
|
||||||
|
#'
|
||||||
|
#' Author: SmartCane Team
|
||||||
|
#' Date: 2025-06-24
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# CONFIGURATION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Package requirements with your current working versions
|
||||||
|
REQUIRED_PACKAGES <- list(
|
||||||
|
# Core data manipulation
|
||||||
|
"dplyr" = "1.1.4",
|
||||||
|
"here" = "1.0.1",
|
||||||
|
"lubridate" = "1.9.4",
|
||||||
|
"readr" = "2.1.5",
|
||||||
|
"readxl" = "1.4.5",
|
||||||
|
"stringr" = "1.5.1",
|
||||||
|
"tidyr" = "1.3.1",
|
||||||
|
"purrr" = "1.0.2",
|
||||||
|
"magrittr" = "2.0.0", # Adding this as it's commonly used
|
||||||
|
|
||||||
|
# Spatial data
|
||||||
|
"exactextractr" = "0.10.0",
|
||||||
|
"raster" = "3.6.32",
|
||||||
|
"sf" = "1.0.19",
|
||||||
|
"terra" = "1.8.43", # CRITICAL: for raster processing
|
||||||
|
|
||||||
|
# Visualization - CRITICAL: tmap v4 for new syntax
|
||||||
|
"ggplot2" = "3.5.1",
|
||||||
|
"tmap" = "4.0", # CRITICAL: for tm_scale_continuous() syntax
|
||||||
|
"gridExtra" = "2.3",
|
||||||
|
# Reporting
|
||||||
|
"knitr" = "1.50",
|
||||||
|
"rmarkdown" = "2.21.0", # Adding this as it's needed for reports
|
||||||
|
|
||||||
|
# Tidyverse meta-package
|
||||||
|
"tidyverse" = "2.0.0",
|
||||||
|
|
||||||
|
# Machine Learning & Statistics
|
||||||
|
"caret" = "7.0.1",
|
||||||
|
"CAST" = "1.0.3",
|
||||||
|
"randomForest" = "4.7.1.2",
|
||||||
|
"rsample" = "1.3.0",
|
||||||
|
|
||||||
|
# Parallel processing
|
||||||
|
"furrr" = "0.3.1",
|
||||||
|
"future" = "1.40.0",
|
||||||
|
"progressr" = "0.15.1",
|
||||||
|
|
||||||
|
# Other utilities
|
||||||
|
"reshape2" = "1.4.4",
|
||||||
|
"zoo" = "1.8.13"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Log file setup
|
||||||
|
LOG_FILE <- file.path(getwd(), "package_manager.log")
|
||||||
|
START_TIME <- Sys.time()
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# UTILITY FUNCTIONS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
#' Log message to both console and file
|
||||||
|
log_message <- function(message, level = "INFO") {
|
||||||
|
timestamp <- format(Sys.time(), "%Y-%m-%d %H:%M:%S")
|
||||||
|
formatted_msg <- sprintf("[%s] %s - %s", level, timestamp, message)
|
||||||
|
|
||||||
|
# Print to console
|
||||||
|
cat(formatted_msg, "\n")
|
||||||
|
|
||||||
|
# Write to log file
|
||||||
|
cat(formatted_msg, "\n", file = LOG_FILE, append = TRUE)
|
||||||
|
}
|
||||||
|
|
||||||
|
#' Check if package is installed
|
||||||
|
is_package_installed <- function(package) {
|
||||||
|
package %in% rownames(installed.packages())
|
||||||
|
}
|
||||||
|
|
||||||
|
#' Get installed package version
|
||||||
|
get_package_version <- function(package) {
|
||||||
|
if (is_package_installed(package)) {
|
||||||
|
as.character(packageVersion(package))
|
||||||
|
} else {
|
||||||
|
NULL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#' Compare version strings (returns TRUE if installed >= required)
|
||||||
|
version_meets_requirement <- function(installed, required) {
|
||||||
|
if (is.null(installed)) return(FALSE)
|
||||||
|
utils::compareVersion(installed, required) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#' Install or update package to minimum version
|
||||||
|
install_or_update_package <- function(package, required_version) {
|
||||||
|
current_version <- get_package_version(package)
|
||||||
|
|
||||||
|
if (is.null(current_version)) {
|
||||||
|
log_message(sprintf("Installing %s (required: >= %s)", package, required_version))
|
||||||
|
tryCatch({
|
||||||
|
install.packages(package, dependencies = TRUE, quiet = TRUE)
|
||||||
|
new_version <- get_package_version(package)
|
||||||
|
log_message(sprintf("✓ Installed %s version %s", package, new_version), "SUCCESS")
|
||||||
|
return(TRUE)
|
||||||
|
}, error = function(e) {
|
||||||
|
log_message(sprintf("✗ Failed to install %s: %s", package, e$message), "ERROR")
|
||||||
|
return(FALSE)
|
||||||
|
})
|
||||||
|
} else if (!version_meets_requirement(current_version, required_version)) {
|
||||||
|
log_message(sprintf("Updating %s from %s to >= %s", package, current_version, required_version))
|
||||||
|
tryCatch({
|
||||||
|
install.packages(package, dependencies = TRUE, quiet = TRUE)
|
||||||
|
new_version <- get_package_version(package)
|
||||||
|
if (version_meets_requirement(new_version, required_version)) {
|
||||||
|
log_message(sprintf("✓ Updated %s to version %s", package, new_version), "SUCCESS")
|
||||||
|
return(TRUE)
|
||||||
|
} else {
|
||||||
|
log_message(sprintf("⚠ %s updated to %s but still below required %s", package, new_version, required_version), "WARNING")
|
||||||
|
return(FALSE)
|
||||||
|
}
|
||||||
|
}, error = function(e) {
|
||||||
|
log_message(sprintf("✗ Failed to update %s: %s", package, e$message), "ERROR")
|
||||||
|
return(FALSE)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
log_message(sprintf("✓ %s version %s meets requirement (>= %s)", package, current_version, required_version))
|
||||||
|
return(TRUE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# MAIN PACKAGE MANAGEMENT FUNCTIONS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
#' Initialize renv if not already initialized
|
||||||
|
initialize_renv <- function() {
|
||||||
|
log_message("Checking renv initialization...")
|
||||||
|
|
||||||
|
if (!file.exists("renv.lock")) {
|
||||||
|
log_message("Initializing renv for the first time...")
|
||||||
|
if (!requireNamespace("renv", quietly = TRUE)) {
|
||||||
|
log_message("Installing renv...")
|
||||||
|
install.packages("renv")
|
||||||
|
}
|
||||||
|
renv::init()
|
||||||
|
log_message("✓ renv initialized", "SUCCESS")
|
||||||
|
} else {
|
||||||
|
log_message("✓ renv already initialized")
|
||||||
|
# Check if renv is already active by looking at the library path
|
||||||
|
if (!requireNamespace("renv", quietly = TRUE)) {
|
||||||
|
install.packages("renv")
|
||||||
|
}
|
||||||
|
# Check if we're already using the renv project library
|
||||||
|
lib_paths <- .libPaths()
|
||||||
|
|
||||||
|
if (!any(grepl("renv", lib_paths))) {
|
||||||
|
log_message("Activating renv...")
|
||||||
|
renv::activate()
|
||||||
|
log_message("✓ renv activated")
|
||||||
|
} else {
|
||||||
|
log_message("✓ renv already active")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#' Check and install all required packages
|
||||||
|
manage_packages <- function() {
|
||||||
|
log_message("=== PACKAGE MANAGEMENT STARTED ===")
|
||||||
|
log_message(sprintf("R version: %s", R.version.string))
|
||||||
|
|
||||||
|
success_count <- 0
|
||||||
|
failure_count <- 0
|
||||||
|
|
||||||
|
for (package in names(REQUIRED_PACKAGES)) {
|
||||||
|
required_version <- REQUIRED_PACKAGES[[package]]
|
||||||
|
|
||||||
|
if (install_or_update_package(package, required_version)) {
|
||||||
|
success_count <- success_count + 1
|
||||||
|
} else {
|
||||||
|
failure_count <- failure_count + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_message(sprintf("Package management complete: %d success, %d failures", success_count, failure_count))
|
||||||
|
|
||||||
|
if (failure_count > 0) {
|
||||||
|
log_message("Some packages failed to install/update. Check log for details.", "WARNING")
|
||||||
|
}
|
||||||
|
|
||||||
|
return(failure_count == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#' Update renv lockfile with current package versions
|
||||||
|
update_lockfile <- function() {
|
||||||
|
log_message("Updating renv lockfile...")
|
||||||
|
tryCatch({
|
||||||
|
renv::snapshot(prompt = FALSE)
|
||||||
|
log_message("✓ renv lockfile updated", "SUCCESS")
|
||||||
|
}, error = function(e) {
|
||||||
|
log_message(sprintf("✗ Failed to update lockfile: %s", e$message), "ERROR")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#' Generate package report
|
||||||
|
generate_package_report <- function() {
|
||||||
|
log_message("=== PACKAGE REPORT ===")
|
||||||
|
|
||||||
|
# Check each required package
|
||||||
|
for (package in names(REQUIRED_PACKAGES)) {
|
||||||
|
required_version <- REQUIRED_PACKAGES[[package]]
|
||||||
|
current_version <- get_package_version(package)
|
||||||
|
|
||||||
|
if (is.null(current_version)) {
|
||||||
|
status <- "❌ NOT INSTALLED"
|
||||||
|
} else if (version_meets_requirement(current_version, required_version)) {
|
||||||
|
status <- "✅ OK"
|
||||||
|
} else {
|
||||||
|
status <- "⚠️ VERSION TOO OLD"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_message(sprintf("%-20s | Required: >= %-8s | Installed: %-8s | %s",
|
||||||
|
package, required_version,
|
||||||
|
ifelse(is.null(current_version), "NONE", current_version),
|
||||||
|
status))
|
||||||
|
}
|
||||||
|
|
||||||
|
log_message("=== END PACKAGE REPORT ===")
|
||||||
|
}
|
||||||
|
|
||||||
|
#' Main function to run complete package management
|
||||||
|
run_package_manager <- function() {
|
||||||
|
# Initialize log
|
||||||
|
cat("", file = LOG_FILE) # Clear log file
|
||||||
|
log_message("SmartCane Project - Package Manager Started")
|
||||||
|
log_message(sprintf("Working directory: %s", getwd()))
|
||||||
|
|
||||||
|
# Step 1: Initialize renv
|
||||||
|
initialize_renv()
|
||||||
|
|
||||||
|
# Step 2: Generate initial report
|
||||||
|
log_message("\n=== INITIAL STATE ===")
|
||||||
|
generate_package_report()
|
||||||
|
|
||||||
|
# Step 3: Manage packages
|
||||||
|
log_message("\n=== PACKAGE INSTALLATION/UPDATES ===")
|
||||||
|
success <- manage_packages()
|
||||||
|
|
||||||
|
# Step 4: Update lockfile if successful
|
||||||
|
if (success) {
|
||||||
|
update_lockfile()
|
||||||
|
}
|
||||||
|
|
||||||
|
# Step 5: Generate final report
|
||||||
|
log_message("\n=== FINAL STATE ===")
|
||||||
|
generate_package_report()
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
end_time <- Sys.time()
|
||||||
|
duration <- round(as.numeric(difftime(end_time, START_TIME, units = "secs")), 2)
|
||||||
|
|
||||||
|
log_message(sprintf("Package management completed in %s seconds", duration))
|
||||||
|
log_message(sprintf("Log saved to: %s", LOG_FILE))
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
log_message("🎉 All packages successfully managed!", "SUCCESS")
|
||||||
|
log_message("📋 Next steps:")
|
||||||
|
log_message(" 1. Test your R scripts to ensure everything works")
|
||||||
|
log_message(" 2. Commit renv.lock to version control")
|
||||||
|
log_message(" 3. Share this script with your team")
|
||||||
|
} else {
|
||||||
|
log_message("⚠️ Some issues occurred. Check the log for details.", "WARNING")
|
||||||
|
log_message("💡 You may need to:")
|
||||||
|
log_message(" 1. Update R to a newer version")
|
||||||
|
log_message(" 2. Install system dependencies")
|
||||||
|
log_message(" 3. Check your internet connection")
|
||||||
|
}
|
||||||
|
|
||||||
|
return(success)
|
||||||
|
}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# EXECUTION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Only run if script is sourced directly (not when loaded as module)
|
||||||
|
if (!exists("PACKAGE_MANAGER_LOADED")) {
|
||||||
|
PACKAGE_MANAGER_LOADED <- TRUE
|
||||||
|
|
||||||
|
cat("🚀 SmartCane Package Manager\n")
|
||||||
|
cat("============================\n")
|
||||||
|
cat("This will check and install/update all required R packages.\n")
|
||||||
|
cat("Log file:", LOG_FILE, "\n\n")
|
||||||
|
|
||||||
|
# Ask for confirmation
|
||||||
|
response <- readline("Continue? (y/N): ")
|
||||||
|
if (tolower(substr(response, 1, 1)) == "y") {
|
||||||
|
result <- run_package_manager()
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
cat("\n✅ Package management completed successfully!\n")
|
||||||
|
} else {
|
||||||
|
cat("\n❌ Package management completed with errors. Check the log.\n")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cat("❌ Package management cancelled.\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
1334
renv/activate.R
Normal file
1334
renv/activate.R
Normal file
File diff suppressed because it is too large
Load diff
19
renv/settings.json
Normal file
19
renv/settings.json
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"bioconductor.version": null,
|
||||||
|
"external.libraries": [],
|
||||||
|
"ignored.packages": [],
|
||||||
|
"package.dependency.fields": [
|
||||||
|
"Imports",
|
||||||
|
"Depends",
|
||||||
|
"LinkingTo"
|
||||||
|
],
|
||||||
|
"ppm.enabled": null,
|
||||||
|
"ppm.ignored.urls": [],
|
||||||
|
"r.version": null,
|
||||||
|
"snapshot.type": "implicit",
|
||||||
|
"use.cache": true,
|
||||||
|
"vcs.ignore.cellar": true,
|
||||||
|
"vcs.ignore.library": true,
|
||||||
|
"vcs.ignore.local": true,
|
||||||
|
"vcs.manage.ignores": true
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue