Skip to content

Commit 37bb228

Browse files
committed
Get Rtools data from API (incomplete)
[ci skip]
1 parent f2fd9e9 commit 37bb228

File tree

10 files changed

+114
-4
lines changed

10 files changed

+114
-4
lines changed

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ lazy_static = "1.4.0"
3434
libc = "0.2"
3535
log = "0.4"
3636
nix = { version = "0.28.0", features = ["fs", "user"] }
37+
once_cell = "1.21.3"
3738
path-clean = "1.0.1"
3839
rand = "0.8.5"
3940
regex = "1.5.4"

src/hardcoded.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
use once_cell::sync::Lazy;
3+
use serde_json::{json, Value};
4+
5+
pub static HC_RTOOLS_AARCH64: Lazy<Value> = Lazy::new(|| {
6+
let data = include_str!("json/rtools-versions-aarch64.json");
7+
serde_json::from_str(data).expect("Invalid JSON in json/rtools-versions-aarch64.json")
8+
});
9+
10+
pub static HC_RTOOLS: Lazy<Value> = Lazy::new(|| {
11+
let data = include_str!("json/rtools-versions.json");
12+
serde_json::from_str(data).expect("Invalid JSON in json/rtools-versions.json")
13+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"version":"44","url":"https://github.com/r-hub/rtools44/releases/download/latest/rtools44-aarch64.exe","first":"4.4.0","last":"4.4.100"},{"version":"45","url":"https://github.com/r-hub/rtools45/releases/download/latest/rtools45-aarch64.exe","first":"4.5.0","last":"100.0.0"}]

src/json/rtools-versions.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"version":"26","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools26.exe","first":"2.0.0","last":"2.6.2"},{"version":"27","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools27.exe","first":"2.6.0","last":"2.7.2"},{"version":"28","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools28.exe","first":"2.7.0","last":"2.8.1"},{"version":"29","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools29.exe","first":"2.8.0","last":"2.9.2"},{"version":"210","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools210.exe","first":"2.9.0","last":"2.10.1"},{"version":"211","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools211.exe","first":"2.10.0","last":"2.11.1"},{"version":"212","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools212.exe","first":"2.12.0","last":"2.12.2"},{"version":"213","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools213.exe","first":"2.13.0","last":"2.13.2"},{"version":"214","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools214.exe","first":"2.13.0","last":"2.14.2"},{"version":"215","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools215.exe","first":"2.14.2","last":"2.15.1"},{"version":"30","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools30.exe","first":"2.15.2","last":"3.0.3"},{"version":"31","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools31.exe","first":"3.0.0","last":"3.1.3"},{"version":"32","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools32.exe","first":"3.1.0","last":"3.2.5"},{"version":"33","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools33.exe","first":"3.2.0","last":"3.3.3"},{"version":"34","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools34.exe","first":"3.3.0","last":"3.6.3"},{"version":"35","url":"https://cran.rstudio.com/bin/windows/Rtools/Rtools35.exe","first":"3.3.0","last":"3.6.3"},{"version":"40","url":"https://cran.rstudio.com/bin/windows/Rtools/rtools40-x86_64.exe","first":"4.0.0","last":"4.2.100"},{"version":"42","url":"https://github.com/r-hub/rtools42/releases/download/latest/rtools42.exe","first":"4.2.0","last":"4.2.100"},{"version":"43","url":"https://github.com/r-hub/rtools43/releases/download/latest/rtools43.exe","first":"4.3.0","last":"4.3.100"},{"version":"44","url":"https://github.com/r-hub/rtools44/releases/download/latest/rtools44.exe","first":"4.4.0","last":"4.4.100"},{"version":"45","url":"https://github.com/r-hub/rtools45/releases/download/latest/rtools45.exe","first":"4.5.0","last":"100.0.0"}]

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ mod common;
2020
mod config;
2121
mod download;
2222
mod escalate;
23+
mod hardcoded;
2324
mod library;
2425
mod macos;
2526
mod renv;

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ mod library;
3333
mod common;
3434
mod config;
3535
mod download;
36+
mod hardcoded;
3637
mod renv;
3738
mod resolve;
3839
mod rversion;

src/resolve.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@ use std::error::Error;
33

44
use clap::ArgMatches;
55
use simple_error::bail;
6+
use simplelog::*;
7+
use std::sync::{LazyLock, RwLock};
8+
use serde_json::{json, Map, Value};
69

710
use crate::common::*;
811
use crate::download::*;
912
use crate::rversion::*;
1013
use crate::utils::*;
14+
use crate::hardcoded::*;
1115

1216
const API_URI: &str = "https://api.r-hub.io/rversions/resolve/";
17+
const API_ROOT: &str = "https://api.r-hib.io/rversions/";
1318

1419
pub fn get_resolve(args: &ArgMatches) -> Result<Rversion, Box<dyn Error>> {
1520
let platform = get_platform(args)?;
@@ -91,3 +96,77 @@ async fn resolve_version(
9196
ppmurl: ppmurl
9297
})
9398
}
99+
100+
static API_CACHE: LazyLock<RwLock<Map<String, Value>>> = LazyLock::new(|| {
101+
RwLock::new(Map::new())
102+
});
103+
104+
fn cache_set_value(key: &str, value: Value) {
105+
let mut map = API_CACHE.write().unwrap();
106+
map.insert(key.to_string(), value);
107+
}
108+
109+
fn cache_get_value(key: &str) -> Option<Value> {
110+
let map = API_CACHE.read().unwrap();
111+
map.get(key).cloned()
112+
}
113+
114+
pub fn get_rtools_versions(arch: &str) -> serde_json::Value {
115+
let cache_key = "rtools".to_string() + arch;
116+
let value = match cache_get_value(&cache_key) {
117+
Some(cached) => cached,
118+
None => {
119+
let url = API_ROOT.to_string() + "/rtools-versions/" + arch;
120+
let val = match download_json_sync(vec![url]) {
121+
Ok(dl) => {
122+
cache_set_value(&cache_key, dl[0].clone());
123+
dl[0].clone()
124+
},
125+
Err(x) => {
126+
warn!("Failed to download Rtools version data, will use \
127+
hardcoded data instead.");
128+
if arch == "aarch64" {
129+
HC_RTOOLS_AARCH64.clone()
130+
} else {
131+
HC_RTOOLS.clone()
132+
}
133+
}
134+
};
135+
val
136+
}
137+
};
138+
139+
value
140+
}
141+
142+
pub fn get_rtools_version(version: &str, arch: &str)
143+
-> Result<RtoolsVersion, Box<dyn Error>> {
144+
145+
let value = get_rtools_versions(arch);
146+
147+
let msg = "Cannot parse response from the R version API to learn about \
148+
Rtools versions";
149+
150+
let value = match value.as_array() {
151+
Some(x) => x,
152+
None => bail!(msg)
153+
};
154+
155+
156+
for ver in value {
157+
let versionx: String = ver["version"].as_str().ok_or(msg)?.to_string();
158+
if &versionx == version {
159+
let url: String = ver["url"].as_str().ok_or(msg)?.to_string();
160+
let first: String = ver["first"].as_str().ok_or(msg)?.to_string();
161+
let last: String = ver["last"].as_str().ok_or(msg)?.to_string();
162+
return Ok(RtoolsVersion {
163+
version: versionx,
164+
url,
165+
first,
166+
last
167+
});
168+
}
169+
}
170+
171+
bail!("Cannot find Rtools version {} for architecture {}", version, arch);
172+
}

src/rversion.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,12 @@ pub struct LinuxTools {
109109
pub is_installed: Vec<String>,
110110
pub delete: Vec<String>,
111111
}
112+
113+
#[cfg(target_os = "windows")]
114+
#[derive(Default, Debug)]
115+
pub struct RtoolsVersion {
116+
pub version: String,
117+
pub url: String,
118+
pub first: String,
119+
pub last: String
120+
}

src/windows.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ fn add_rtools(version: String) -> Result<(), Box<dyn Error>> {
164164
} else {
165165
vers = vec![version.replace("rtools", "")];
166166
}
167+
let myarch = arch();
168+
let suffix = if myarch == whoami::Arch::Arm64 { "-aarch64" } else { "" };
167169
let client = &reqwest::Client::new();
168170
for ver in vers {
169171
let rtools45 = &ver[0..2] == "45";
@@ -174,7 +176,8 @@ fn add_rtools(version: String) -> Result<(), Box<dyn Error>> {
174176
let filename: String;
175177
let url: String;
176178
if rtools45 {
177-
let rt45=Path::new("C:\\Rtools45");
179+
let rt45path = "C:\\Rtools45".to_owned() + suffix;
180+
let rt45=Path::new(&rt45path);
178181
if rt45.exists() {
179182
info!("Rtools45 is already installed");
180183
continue;
@@ -725,7 +728,7 @@ pub fn sc_set_default(ver: &str) -> Result<(), Box<dyn Error>> {
725728

726729
pub fn unset_default() -> Result<(), Box<dyn Error>> {
727730
escalate("unsetting the default R version")?;
728-
731+
729732
fn try_rm(x: &str) {
730733
let linkdir = Path::new(RIG_LINKS_DIR);
731734
let f = linkdir.join(x);

0 commit comments

Comments
 (0)