diff --git a/src/help-linux.in b/src/help-linux.in index 8ced196f..b7bfa0c2 100644 --- a/src/help-linux.in +++ b/src/help-linux.in @@ -108,6 +108,9 @@ const HELP_ADD: &str = " - `rig add x.y` adds the latest release within the `x.y` minor branch. - `rig add oldrel/n` adds the latest release within the `n`th previous minor branch (`oldrel` is the same as `oldrel/1`). + - `rig add renv.lock` or `rig add ` installs the R version specified + in the renv.lock file. If a directory is given, rig looks for an + renv.lock file in that directory. You need to run this command with `sudo`: `sudo rig add ...`, otherwise rig will need to ask for your password. @@ -130,7 +133,13 @@ const HELP_ADD_EXAMPLES: &str = "\x1b[4m\x1b[1mExamples:\x1b[22m\x1b[24m rig add 4.1.2 # Install latest version within a minor branch - rig add 4.1"; + rig add 4.1 + + # Install the R version specified in renv.lock + rig add renv.lock + + # Install R version from a project's renv.lock + rig add path/to/project"; const HELP_RM: &str = " \x1b[4m\x1b[1mDescription:\x1b[22m\x1b[24m diff --git a/src/help-macos.in b/src/help-macos.in index 65822bb3..d63b2921 100644 --- a/src/help-macos.in +++ b/src/help-macos.in @@ -115,6 +115,9 @@ const HELP_ADD: &str = " - `rig add oldrel/n` adds the latest release within the `n`th previous minor branch (`oldrel` is the same as `oldrel/1`). - `rig add ` uses a `.pkg` installer from ``. + - `rig add renv.lock` or `rig add ` installs the R version specified + in the renv.lock file. If a directory is given, rig looks for an + renv.lock file in that directory. Usually you need to run this command with `sudo`: `sudo rig add ...`, otherwise rig will need to ask for your password. @@ -150,7 +153,13 @@ const HELP_ADD_EXAMPLES: &str = "\x1b[4m\x1b[1mExamples:\x1b[22m\x1b[24m rig add -a arm64 release # Install x86_64 build of R (default on x86_64 macs) - rig add -a x86_64 release"; + rig add -a x86_64 release + + # Install the R version specified in renv.lock + rig add renv.lock + + # Install R version from a project's renv.lock + rig add path/to/project"; const HELP_RM: &str = " \x1b[4m\x1b[1mDescription:\x1b[22m\x1b[24m diff --git a/src/help-windows.in b/src/help-windows.in index 6cf0cf9e..af0a1d57 100644 --- a/src/help-windows.in +++ b/src/help-windows.in @@ -110,6 +110,9 @@ const HELP_ADD: &str = " - `rig add oldrel/n` adds the latest release within the `n`th previous minor branch (`oldrel` is the same as `oldrel/1`). - `rig add ` uses a `.pkg` installer from ``. + - `rig add renv.lock` or `rig add ` installs the R version specified + in the renv.lock file. If a directory is given, rig looks for an + renv.lock file in that directory. `rig add` will call the following rig command after the installation, to set up the newly installed version: @@ -149,7 +152,13 @@ const HELP_ADD_EXAMPLES: &str = "\x1b[4m\x1b[1mExamples:\x1b[22m\x1b[24m rig add 4.1 # Install all needed Rtools versions - rig add rtools"; + rig add rtools + + # Install the R version specified in renv.lock + rig add renv.lock + + # Install R version from a project's renv.lock + rig add path/to/project"; const HELP_RM: &str = " \x1b[4m\x1b[1mDescription:\x1b[22m\x1b[24m diff --git a/src/resolve.rs b/src/resolve.rs index 8b1faac4..304970c8 100644 --- a/src/resolve.rs +++ b/src/resolve.rs @@ -11,11 +11,14 @@ use simple_error::bail; #[cfg(target_os = "windows")] use std::sync::{LazyLock, RwLock}; +use std::path::Path; + use crate::common::*; use crate::download::*; #[cfg(target_os = "windows")] use crate::hardcoded::*; use crate::output::OUTPUT; +use crate::renv; use crate::rversion::*; use crate::utils::*; @@ -23,10 +26,41 @@ const API_URI: &str = "https://api.r-hub.io/rversions/resolve/"; #[cfg(target_os = "windows")] const API_ROOT: &str = "https://api.r-hub.io/rversions/"; +pub fn resolve_lockfile_version(str: &str) -> Result, Box> { + let path = Path::new(str); + + // Direct path to renv.lock + if path.file_name() == Some(std::ffi::OsStr::new("renv.lock")) && path.exists() { + let ver = renv::parse_r_version(path.to_path_buf())?; + OUTPUT.info(&format!("Installing R {} from renv.lock", ver)); + return Ok(Some(ver)); + } + + // Directory containing renv.lock + if path.is_dir() { + let lockfile = path.join("renv.lock"); + if lockfile.exists() { + let ver = renv::parse_r_version(lockfile)?; + OUTPUT.info(&format!("Installing R {} from renv.lock", ver)); + return Ok(Some(ver)); + } + } + + Ok(None) +} + pub fn get_resolve(args: &ArgMatches) -> Result> { let platform = get_platform(args)?; let arch = get_arch(&platform, args); let str: &String = args.get_one("str").unwrap(); + + // Check if str is a path to renv.lock or a directory containing one + let resolved_ver = resolve_lockfile_version(str)?; + let str = match &resolved_ver { + Some(ver) => ver.as_str(), + None => str.as_str(), + }; + let eps = vec![str.to_string()]; if str.len() > 8 && (&str[..7] == "http://" || &str[..8] == "https://") { @@ -186,3 +220,57 @@ pub fn get_rtools_version(version: &str, arch: &str) -> Result