Skip to content

Commit 769d71e

Browse files
authored
Merge pull request #2377 from itowlson/override-download-cache-dir
More forgiving caching
2 parents 95d597b + 2a156a9 commit 769d71e

File tree

4 files changed

+43
-10
lines changed

4 files changed

+43
-10
lines changed

crates/loader/src/cache.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
33
use anyhow::{ensure, Context, Result};
44

5-
use std::path::{Path, PathBuf};
5+
use std::{
6+
path::PathBuf,
7+
sync::atomic::{AtomicBool, Ordering},
8+
};
69

710
use crate::fs::{create_dir_all, write_file};
811

@@ -17,6 +20,9 @@ const DATA_DIR: &str = "data";
1720
pub struct Cache {
1821
/// Root directory for the cache instance.
1922
root: PathBuf,
23+
/// Whether the cache directories have been checked to exist (and
24+
/// created if necessary).
25+
dirs_ensured_once: AtomicBool,
2026
}
2127

2228
impl Cache {
@@ -29,9 +35,11 @@ impl Cache {
2935
.join(CONFIG_DIR),
3036
};
3137
let root = root.join(REGISTRY_CACHE_DIR);
32-
Self::ensure_dirs(&root).await?;
3338

34-
Ok(Self { root })
39+
Ok(Self {
40+
root,
41+
dirs_ensured_once: AtomicBool::new(false),
42+
})
3543
}
3644

3745
/// The manifests directory for the current cache.
@@ -80,12 +88,14 @@ impl Cache {
8088

8189
/// Write the contents in the cache's wasm directory.
8290
pub async fn write_wasm(&self, bytes: impl AsRef<[u8]>, digest: impl AsRef<str>) -> Result<()> {
91+
self.ensure_dirs().await?;
8392
write_file(&self.wasm_path(digest), bytes.as_ref()).await?;
8493
Ok(())
8594
}
8695

8796
/// Write the contents in the cache's data directory.
8897
pub async fn write_data(&self, bytes: impl AsRef<[u8]>, digest: impl AsRef<str>) -> Result<()> {
98+
self.ensure_dirs().await?;
8999
write_file(&self.data_path(digest), bytes.as_ref()).await?;
90100
Ok(())
91101
}
@@ -106,8 +116,16 @@ impl Cache {
106116
/// └──manifests
107117
/// └──wasm
108118
/// └─-data
109-
async fn ensure_dirs(root: &Path) -> Result<()> {
110-
tracing::debug!("using cache root directory {}", root.display());
119+
pub async fn ensure_dirs(&self) -> Result<()> {
120+
tracing::debug!("using cache root directory {}", self.root.display());
121+
122+
// We don't care about ordering as this function is idempotent -
123+
// we are using an Atomic only for interior mutability.
124+
if self.dirs_ensured_once.load(Ordering::Relaxed) {
125+
return Ok(());
126+
}
127+
128+
let root = &self.root;
111129

112130
let p = root.join(MANIFESTS_DIR);
113131
if !p.is_dir() {
@@ -130,12 +148,14 @@ impl Cache {
130148
.with_context(|| format!("failed to create assets directory `{}`", p.display()))?;
131149
}
132150

151+
self.dirs_ensured_once.store(true, Ordering::Relaxed);
152+
133153
Ok(())
134154
}
135155
}
136156

137157
#[cfg(windows)]
138-
fn safe_name(digest: impl AsRef<str>) -> impl AsRef<Path> {
158+
fn safe_name(digest: impl AsRef<str>) -> impl AsRef<std::path::Path> {
139159
digest.as_ref().replace(':', "_")
140160
}
141161

crates/loader/src/local.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ impl LocalLoader {
241241
} else {
242242
let _loading_permit = self.file_loading_permits.acquire().await?;
243243

244+
self.cache.ensure_dirs().await?;
244245
let dest = self.cache.wasm_path(digest);
245246
verified_download(url, digest, &dest)
246247
.await

src/commands/registry.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ pub struct Push {
5757
/// This is a string whose format is defined by the registry standard, and generally consists of <registry>/<username>/<application-name>:<version>. E.g. ghcr.io/ogghead/spin-test-app:0.1.0
5858
#[clap()]
5959
pub reference: String,
60+
61+
/// Cache directory for downloaded registry data.
62+
#[clap(long)]
63+
pub cache_dir: Option<PathBuf>,
6064
}
6165

6266
impl Push {
@@ -66,7 +70,7 @@ impl Push {
6670
spin_build::build(&app_file, &[]).await?;
6771
}
6872

69-
let mut client = spin_oci::Client::new(self.insecure, None).await?;
73+
let mut client = spin_oci::Client::new(self.insecure, self.cache_dir.clone()).await?;
7074

7175
let _spinner = create_dotted_spinner(2000, "Pushing app to the Registry".to_owned());
7276

@@ -95,12 +99,16 @@ pub struct Pull {
9599
/// This is a string whose format is defined by the registry standard, and generally consists of <registry>/<username>/<application-name>:<version>. E.g. ghcr.io/ogghead/spin-test-app:0.1.0
96100
#[clap()]
97101
pub reference: String,
102+
103+
/// Cache directory for downloaded registry data.
104+
#[clap(long)]
105+
pub cache_dir: Option<PathBuf>,
98106
}
99107

100108
impl Pull {
101109
/// Pull a Spin application from an OCI registry
102110
pub async fn run(self) -> Result<()> {
103-
let mut client = spin_oci::Client::new(self.insecure, None).await?;
111+
let mut client = spin_oci::Client::new(self.insecure, self.cache_dir.clone()).await?;
104112

105113
let _spinner = create_dotted_spinner(2000, "Pulling app from the Registry".to_owned());
106114

src/commands/up.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ pub struct UpCommand {
9595
#[clap(long = "temp", alias = "tmp")]
9696
pub tmp: Option<PathBuf>,
9797

98+
/// Cache directory for downloaded components and assets.
99+
#[clap(long)]
100+
pub cache_dir: Option<PathBuf>,
101+
98102
/// For local apps with directory mounts and no excluded files, mount them directly instead of using a temporary
99103
/// directory.
100104
///
@@ -421,7 +425,7 @@ impl UpCommand {
421425
// TODO: We could make the `--help` experience a little faster if
422426
// we could fetch just the locked app JSON at this stage.
423427
AppSource::OciRegistry(reference) => {
424-
let mut client = spin_oci::Client::new(self.insecure, None)
428+
let mut client = spin_oci::Client::new(self.insecure, self.cache_dir.clone())
425429
.await
426430
.context("cannot create registry client")?;
427431

@@ -448,7 +452,7 @@ impl UpCommand {
448452
} else {
449453
FilesMountStrategy::Copy(working_dir.join("assets"))
450454
};
451-
spin_loader::from_file(&manifest_path, files_mount_strategy, None)
455+
spin_loader::from_file(&manifest_path, files_mount_strategy, self.cache_dir.clone())
452456
.await
453457
.with_context(|| {
454458
format!(

0 commit comments

Comments
 (0)