Skip to content

Commit dafa1d2

Browse files
committed
Implement --no-cache global parameter
1 parent 7e16311 commit dafa1d2

16 files changed

Lines changed: 247 additions & 7 deletions

src/args.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2233,6 +2233,13 @@ pub fn rig_app() -> Command {
22332233
.long("admin")
22342234
.global(true)
22352235
.action(clap::ArgAction::SetTrue),
2236+
)
2237+
.arg(
2238+
Arg::new("no-cache")
2239+
.help("Do not read or write rig's cache (overrides RIG_NO_CACHE and config)")
2240+
.long("no-cache")
2241+
.global(true)
2242+
.action(clap::ArgAction::SetTrue),
22362243
);
22372244

22382245
rig = rig

src/built.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ impl BuiltCache {
7373
/// Never an error: not caching a build is a missed optimization, not a
7474
/// failure, so everything that can go wrong here is logged and dropped.
7575
pub fn new(r_version: &str, r_binary: &str) -> Option<BuiltCache> {
76+
if crate::cache::no_cache() {
77+
debug!("Not caching built packages, --no-cache");
78+
return None;
79+
}
7680
let cache = match get_cache_dir() {
7781
Ok(cache) => cache,
7882
Err(err) => {

src/cache.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,131 @@
11
use std::error::Error;
22
use std::path::PathBuf;
3+
use std::sync::OnceLock;
34

45
use directories::ProjectDirs;
56
use log::*;
67
use simple_error::bail;
78

89
use crate::output::OUTPUT;
910

11+
static NO_CACHE: OnceLock<bool> = OnceLock::new();
12+
13+
/// Record whether this run may use rig's cache, from the `--no-cache` flag.
14+
pub fn set_no_cache(value: bool) -> Result<(), Box<dyn Error>> {
15+
match NO_CACHE.set(value) {
16+
Ok(()) => Ok(()),
17+
Err(existing) if existing == value => Ok(()),
18+
Err(existing) => bail!(
19+
"Cannot set no-cache to {}, already set to {}",
20+
value,
21+
existing
22+
),
23+
}
24+
}
25+
26+
/// Whether this run must neither read nor write rig's cache.
27+
pub fn no_cache() -> bool {
28+
if let Some(cached) = NO_CACHE.get() {
29+
return *cached;
30+
}
31+
32+
let value = if let Ok(val) = std::env::var("RIG_NO_CACHE") {
33+
match parse_bool(&val) {
34+
Some(val) => val,
35+
None => {
36+
warn!(
37+
"Invalid RIG_NO_CACHE value: '{}', expected 'true' or 'false', ignoring it",
38+
val
39+
);
40+
false
41+
}
42+
}
43+
} else {
44+
match crate::config::get_global_config_bool("no-cache") {
45+
Ok(val) => val.unwrap_or(false),
46+
Err(err) => {
47+
warn!("{}, ignoring it", err);
48+
false
49+
}
50+
}
51+
};
52+
53+
let _ = NO_CACHE.set(value);
54+
value
55+
}
56+
57+
fn parse_bool(value: &str) -> Option<bool> {
58+
match value.trim().to_lowercase().as_str() {
59+
"true" | "yes" | "on" | "1" => Some(true),
60+
"false" | "no" | "off" | "0" | "" => Some(false),
61+
_ => None,
62+
}
63+
}
64+
1065
/// Get the project cache directory
1166
///
1267
/// Returns the cache directory for the rig application.
1368
/// This is used for storing temporary data like downloaded packages.
1469
pub fn get_cache_dir() -> Result<PathBuf, Box<dyn Error>> {
70+
if no_cache() {
71+
return ephemeral_cache_dir();
72+
}
73+
real_cache_dir()
74+
}
75+
76+
/// The persistent cache directory, whatever `--no-cache` says.
77+
pub fn real_cache_dir() -> Result<PathBuf, Box<dyn Error>> {
1578
let cache_dir = ProjectDirs::from("com", "gaborcsardi", "rig")
1679
.ok_or("Cannot determine cache directory")?
1780
.cache_dir()
1881
.to_path_buf();
1982
Ok(cache_dir)
2083
}
2184

85+
static EPHEMERAL_CACHE_DIR: OnceLock<PathBuf> = OnceLock::new();
86+
87+
fn ephemeral_cache_dir() -> Result<PathBuf, Box<dyn Error>> {
88+
if let Some(dir) = EPHEMERAL_CACHE_DIR.get() {
89+
return Ok(dir.clone());
90+
}
91+
92+
let dir = std::env::temp_dir().join(ephemeral_cache_dir_name());
93+
create_download_dir_checked(&dir)?;
94+
debug!("Using the throwaway cache directory {}", dir.display());
95+
let _ = EPHEMERAL_CACHE_DIR.set(dir.clone());
96+
Ok(dir)
97+
}
98+
99+
#[cfg(any(target_os = "macos", target_os = "linux"))]
100+
fn ephemeral_cache_dir_name() -> String {
101+
format!(
102+
"rig-nocache-{}-{}",
103+
nix::unistd::geteuid().as_raw(),
104+
std::process::id()
105+
)
106+
}
107+
108+
#[cfg(target_os = "windows")]
109+
fn ephemeral_cache_dir_name() -> String {
110+
// `%TEMP%` is already per user on Windows, see `default_download_dir()`.
111+
format!("rig-nocache-{}", std::process::id())
112+
}
113+
114+
pub fn cleanup_ephemeral_cache_dir() {
115+
let dir = match EPHEMERAL_CACHE_DIR.get() {
116+
Some(dir) => dir,
117+
None => return,
118+
};
119+
match std::fs::remove_dir_all(dir) {
120+
Ok(()) => debug!("Removed the throwaway cache directory {}", dir.display()),
121+
Err(err) => debug!(
122+
"Cannot remove the throwaway cache directory {}: {}",
123+
dir.display(),
124+
err
125+
),
126+
}
127+
}
128+
22129
/// Get the project data directory
23130
///
24131
/// Returns the data directory for the rig application.

src/config.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,29 @@ pub fn get_global_config_value(key: &str) -> Result<Option<String>, Box<dyn Erro
181181
}
182182
}
183183

184+
/// A boolean configuration entry.
185+
pub fn get_global_config_bool(key: &str) -> Result<Option<bool>, Box<dyn Error>> {
186+
let map = load_raw_config()?;
187+
match map.get(key) {
188+
None => Ok(None),
189+
Some(serde_json::Value::Bool(b)) => Ok(Some(*b)),
190+
Some(serde_json::Value::String(s)) => match s.as_str() {
191+
"true" => Ok(Some(true)),
192+
"false" => Ok(Some(false)),
193+
_ => bail!(
194+
"Invalid '{}' in rig config: '{}', expected 'true' or 'false'",
195+
key,
196+
s
197+
),
198+
},
199+
Some(other) => bail!(
200+
"Invalid '{}' in rig config: {}, expected 'true' or 'false'",
201+
key,
202+
other
203+
),
204+
}
205+
}
206+
184207
pub fn set_global_config_value(key: &str, value: &str) -> Result<(), Box<dyn Error>> {
185208
let mut map = load_raw_config()?;
186209
map.insert(

src/dirs.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use log::error;
2727
use simple_error::bail;
2828
use tabular::{row, Table};
2929

30-
use crate::cache::{get_cache_dir, get_data_dir, get_download_dir, get_logs_dir};
30+
use crate::cache::{get_data_dir, get_download_dir, get_logs_dir, real_cache_dir};
3131
use crate::output::OUTPUT;
3232
use crate::utils::{get_binary_dir, get_mode};
3333

@@ -143,7 +143,9 @@ pub fn rig_dirs(arch: &str) -> Result<RigDirs, Box<dyn Error>> {
143143
data_dir: path_string(get_data_dir()?),
144144
#[cfg(target_os = "linux")]
145145
fonts_dir: path_string(get_fontconfig_dir()?),
146-
cache_dir: path_string(get_cache_dir()?),
146+
// The real one, not the throwaway directory `--no-cache` swaps in: this
147+
// reports where rig keeps things, not where this process happens to.
148+
cache_dir: path_string(real_cache_dir()?),
147149
download_dir: path_string(get_download_dir()?),
148150
logs_dir: path_string(get_logs_dir()?),
149151
})
@@ -208,7 +210,7 @@ pub fn sc_system_dirs(args: &ArgMatches, mainargs: &ArgMatches) -> Result<(), Bo
208210
#[cfg(target_os = "linux")]
209211
println!("{}", path_string(get_fontconfig_dir()?));
210212
}
211-
"cache" => println!("{}", path_string(get_cache_dir()?)),
213+
"cache" => println!("{}", path_string(real_cache_dir()?)),
212214
"download" => println!("{}", path_string(get_download_dir()?)),
213215
"log" => println!("{}", path_string(get_logs_dir()?)),
214216
_ => unreachable!(),

src/download.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,11 @@ pub fn download_file_sync(
9191
) -> Result<OsString, Box<dyn Error>> {
9292
let tmp_dir = crate::cache::ensure_download_dir()?;
9393
let target = tmp_dir.join(filename);
94-
if target.exists() && (infinite_cache || not_too_old(&target)) {
94+
// `infinite_cache` goes around `not_too_old()`, so `--no-cache` has to be
95+
// checked here as well and not only there.
96+
let cached =
97+
target.exists() && !crate::cache::no_cache() && (infinite_cache || not_too_old(&target));
98+
if cached {
9599
OUTPUT.success(&format!("{} is cached at {}", filename, target.display()));
96100
info!("{} is cached at {}", filename, target.display());
97101
} else {

src/escalate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub fn escalate(task: &str) -> Result<(), Box<dyn Error>> {
4545
"RIG_FONTS_SHA256",
4646
"RIG_FONTS_URL",
4747
"RIG_MODE",
48+
"RIG_NO_CACHE",
4849
"RIG_R_INSTALL_DIR",
4950
"RUST_BACKTRACE",
5051
"http_proxy",

0 commit comments

Comments
 (0)