summaryrefslogtreecommitdiff
path: root/cli/cache
diff options
context:
space:
mode:
Diffstat (limited to 'cli/cache')
-rw-r--r--cli/cache/http_cache.rs144
-rw-r--r--cli/cache/mod.rs1
2 files changed, 98 insertions, 47 deletions
diff --git a/cli/cache/http_cache.rs b/cli/cache/http_cache.rs
index e98f4bad7..c65960086 100644
--- a/cli/cache/http_cache.rs
+++ b/cli/cache/http_cache.rs
@@ -12,7 +12,6 @@ use deno_core::serde::Serialize;
use deno_core::serde_json;
use deno_core::url::Url;
use std::fs;
-use std::fs::File;
use std::io;
use std::path::Path;
use std::path::PathBuf;
@@ -73,32 +72,42 @@ pub fn url_to_filename(url: &Url) -> Option<PathBuf> {
}
/// Cached metadata about a url.
-#[derive(Serialize, Deserialize)]
+#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct CachedUrlMetadata {
pub headers: HeadersMap,
pub url: String,
- #[serde(default = "SystemTime::now")]
- pub now: SystemTime,
+ #[serde(default = "SystemTime::now", rename = "now")]
+ pub time: SystemTime,
}
-impl CachedUrlMetadata {
- pub fn write(&self, cache_filename: &Path) -> Result<(), AnyError> {
- let metadata_filename = Self::filename(cache_filename);
- let json = serde_json::to_string_pretty(self)?;
- util::fs::atomic_write_file(&metadata_filename, json, CACHE_PERM)?;
- Ok(())
+// DO NOT make the path public. The fact that this is stored in a file
+// is an implementation detail.
+pub struct MaybeHttpCacheItem(PathBuf);
+
+impl MaybeHttpCacheItem {
+ #[cfg(test)]
+ pub fn read_to_string(&self) -> Result<Option<String>, AnyError> {
+ let Some(bytes) = self.read_to_bytes()? else {
+ return Ok(None);
+ };
+ Ok(Some(String::from_utf8(bytes)?))
}
- pub fn read(cache_filename: &Path) -> Result<Self, AnyError> {
- let metadata_filename = Self::filename(cache_filename);
- let metadata = fs::read_to_string(metadata_filename)?;
- let metadata: Self = serde_json::from_str(&metadata)?;
- Ok(metadata)
+ pub fn read_to_bytes(&self) -> Result<Option<Vec<u8>>, AnyError> {
+ match std::fs::read(&self.0) {
+ Ok(s) => Ok(Some(s)),
+ Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None),
+ Err(err) => Err(err.into()),
+ }
}
- /// Ex: $DENO_DIR/deps/https/deno.land/c885b7dcf1d6936e33a9cc3a2d74ec79bab5d733d3701c85a029b7f7ec9fbed4.metadata.json
- pub fn filename(cache_filename: &Path) -> PathBuf {
- cache_filename.with_extension("metadata.json")
+ pub fn read_metadata(&self) -> Result<Option<CachedUrlMetadata>, AnyError> {
+ let metadata_filepath = self.0.with_extension("metadata.json");
+ match fs::read_to_string(metadata_filepath) {
+ Ok(metadata) => Ok(Some(serde_json::from_str(&metadata)?)),
+ Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None),
+ Err(err) => Err(err.into()),
+ }
}
}
@@ -131,26 +140,64 @@ impl HttpCache {
})
}
- pub fn get_cache_filename(&self, url: &Url) -> Option<PathBuf> {
- Some(self.location.join(url_to_filename(url)?))
+ pub fn get_modified_time(
+ &self,
+ url: &Url,
+ ) -> Result<Option<SystemTime>, AnyError> {
+ let filepath = self.get_cache_filepath_internal(url)?;
+ match fs::metadata(filepath) {
+ Ok(metadata) => Ok(Some(metadata.modified()?)),
+ Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
+ Err(err) => Err(err.into()),
+ }
+ }
+
+ // DEPRECATED: Where the file is stored and how it's stored should be an implementation
+ // detail of the cache.
+ #[deprecated(note = "Do not assume the cache will be stored at a file path.")]
+ pub fn get_cache_filepath(&self, url: &Url) -> Result<PathBuf, AnyError> {
+ self.get_cache_filepath_internal(url)
+ }
+
+ fn get_cache_filepath_internal(
+ &self,
+ url: &Url,
+ ) -> Result<PathBuf, AnyError> {
+ Ok(
+ self.location.join(
+ url_to_filename(url)
+ .ok_or_else(|| generic_error("Can't convert url to filename."))?,
+ ),
+ )
+ }
+
+ #[cfg(test)]
+ pub fn write_metadata(
+ &self,
+ url: &Url,
+ meta_data: &CachedUrlMetadata,
+ ) -> Result<(), AnyError> {
+ let cache_path = self.get_cache_filepath_internal(url)?;
+ self.write_metadata_at_path(&cache_path, meta_data)
+ }
+
+ fn write_metadata_at_path(
+ &self,
+ path: &Path,
+ meta_data: &CachedUrlMetadata,
+ ) -> Result<(), AnyError> {
+ let cache_path = path.with_extension("metadata.json");
+ let json = serde_json::to_string_pretty(meta_data)?;
+ util::fs::atomic_write_file(&cache_path, json, CACHE_PERM)?;
+ Ok(())
}
// TODO(bartlomieju): this method should check headers file
// and validate against ETAG/Last-modified-as headers.
// ETAG check is currently done in `cli/file_fetcher.rs`.
- pub fn get(
- &self,
- url: &Url,
- ) -> Result<(File, HeadersMap, SystemTime), AnyError> {
- let cache_filename = self.location.join(
- url_to_filename(url)
- .ok_or_else(|| generic_error("Can't convert url to filename."))?,
- );
- let metadata_filename = CachedUrlMetadata::filename(&cache_filename);
- let file = File::open(cache_filename)?;
- let metadata = fs::read_to_string(metadata_filename)?;
- let metadata: CachedUrlMetadata = serde_json::from_str(&metadata)?;
- Ok((file, metadata.headers, metadata.now))
+ pub fn get(&self, url: &Url) -> Result<MaybeHttpCacheItem, AnyError> {
+ let cache_filepath = self.get_cache_filepath_internal(url)?;
+ Ok(MaybeHttpCacheItem(cache_filepath))
}
pub fn set(
@@ -159,24 +206,30 @@ impl HttpCache {
headers_map: HeadersMap,
content: &[u8],
) -> Result<(), AnyError> {
- let cache_filename = self.location.join(
- url_to_filename(url)
- .ok_or_else(|| generic_error("Can't convert url to filename."))?,
- );
+ let cache_filepath = self.get_cache_filepath_internal(url)?;
// Create parent directory
- let parent_filename = cache_filename
+ let parent_filename = cache_filepath
.parent()
.expect("Cache filename should have a parent dir");
self.ensure_dir_exists(parent_filename)?;
// Cache content
- util::fs::atomic_write_file(&cache_filename, content, CACHE_PERM)?;
+ util::fs::atomic_write_file(&cache_filepath, content, CACHE_PERM)?;
let metadata = CachedUrlMetadata {
- now: SystemTime::now(),
+ time: SystemTime::now(),
url: url.to_string(),
headers: headers_map,
};
- metadata.write(&cache_filename)
+ self.write_metadata_at_path(&cache_filepath, &metadata)?;
+
+ Ok(())
+ }
+
+ pub fn contains(&self, url: &Url) -> bool {
+ let Ok(cache_filepath) = self.get_cache_filepath_internal(url) else {
+ return false
+ };
+ cache_filepath.is_file()
}
}
@@ -184,7 +237,6 @@ impl HttpCache {
mod tests {
use super::*;
use std::collections::HashMap;
- use std::io::Read;
use test_util::TempDir;
#[test]
@@ -228,11 +280,9 @@ mod tests {
let r = cache.set(&url, headers, content);
eprintln!("result {r:?}");
assert!(r.is_ok());
- let r = cache.get(&url);
- assert!(r.is_ok());
- let (mut file, headers, _) = r.unwrap();
- let mut content = String::new();
- file.read_to_string(&mut content).unwrap();
+ let cache_item = cache.get(&url).unwrap();
+ let content = cache_item.read_to_string().unwrap().unwrap();
+ let headers = cache_item.read_metadata().unwrap().unwrap().headers;
assert_eq!(content, "Hello world");
assert_eq!(
headers.get("content-type").unwrap(),
diff --git a/cli/cache/mod.rs b/cli/cache/mod.rs
index 772ba10a5..94ccb42e4 100644
--- a/cli/cache/mod.rs
+++ b/cli/cache/mod.rs
@@ -84,6 +84,7 @@ impl Loader for FetchCacher {
return None;
}
+ #[allow(deprecated)]
let local = self.file_fetcher.get_local_path(specifier)?;
if local.is_file() {
let emit = self