summaryrefslogtreecommitdiff
path: root/cli/cache/deno_dir.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2022-11-25 19:04:30 -0500
committerGitHub <noreply@github.com>2022-11-26 00:04:30 +0000
commit0c0af67f89b610eb61e4f66a5dbf665474aa9383 (patch)
treeb2da2181d6ce10395da176ca8ac352345fc65fca /cli/cache/deno_dir.rs
parente0dd275935c49f5b5b844123d621c5dea1761983 (diff)
refactor: `DenoDir` - move to cache folder and make `root_dir` private (#16823)
Diffstat (limited to 'cli/cache/deno_dir.rs')
-rw-r--r--cli/cache/deno_dir.rs218
1 files changed, 218 insertions, 0 deletions
diff --git a/cli/cache/deno_dir.rs b/cli/cache/deno_dir.rs
new file mode 100644
index 000000000..217658c15
--- /dev/null
+++ b/cli/cache/deno_dir.rs
@@ -0,0 +1,218 @@
+// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+
+use super::DiskCache;
+
+use std::path::PathBuf;
+
+/// `DenoDir` serves as coordinator for multiple `DiskCache`s containing them
+/// in single directory that can be controlled with `$DENO_DIR` env variable.
+#[derive(Clone)]
+pub struct DenoDir {
+ /// Example: /Users/rld/.deno/
+ /// Note: This is not exposed in order to encourage using re-usable methods.
+ root: PathBuf,
+ /// Used by TsCompiler to cache compiler output.
+ pub gen_cache: DiskCache,
+}
+
+impl DenoDir {
+ pub fn new(maybe_custom_root: Option<PathBuf>) -> std::io::Result<Self> {
+ let root: PathBuf = if let Some(root) = maybe_custom_root {
+ root
+ } else if let Some(cache_dir) = dirs::cache_dir() {
+ // We use the OS cache dir because all files deno writes are cache files
+ // Once that changes we need to start using different roots if DENO_DIR
+ // is not set, and keep a single one if it is.
+ cache_dir.join("deno")
+ } else if let Some(home_dir) = dirs::home_dir() {
+ // fallback path
+ home_dir.join(".deno")
+ } else {
+ panic!("Could not set the Deno root directory")
+ };
+ let root = if root.is_absolute() {
+ root
+ } else {
+ std::env::current_dir()?.join(root)
+ };
+ assert!(root.is_absolute());
+ let gen_path = root.join("gen");
+
+ let deno_dir = Self {
+ root,
+ gen_cache: DiskCache::new(&gen_path),
+ };
+ deno_dir.gen_cache.ensure_dir_exists(&gen_path)?;
+
+ Ok(deno_dir)
+ }
+
+ /// The root directory of the DENO_DIR for display purposes only.
+ pub fn root_path_for_display(&self) -> std::path::Display {
+ self.root.display()
+ }
+
+ /// Path for the incremental cache used for formatting.
+ pub fn fmt_incremental_cache_db_file_path(&self) -> PathBuf {
+ // bump this version name to invalidate the entire cache
+ self.root.join("fmt_incremental_cache_v1")
+ }
+
+ /// Path for the incremental cache used for linting.
+ pub fn lint_incremental_cache_db_file_path(&self) -> PathBuf {
+ // bump this version name to invalidate the entire cache
+ self.root.join("lint_incremental_cache_v1")
+ }
+
+ /// Path for caching swc dependency analysis.
+ pub fn dep_analysis_db_file_path(&self) -> PathBuf {
+ // bump this version name to invalidate the entire cache
+ self.root.join("dep_analysis_cache_v1")
+ }
+
+ /// Path for caching node analysis.
+ pub fn node_analysis_db_file_path(&self) -> PathBuf {
+ // bump this version name to invalidate the entire cache
+ self.root.join("node_analysis_cache_v1")
+ }
+
+ /// Path for the cache used for type checking.
+ pub fn type_checking_cache_db_file_path(&self) -> PathBuf {
+ // bump this version name to invalidate the entire cache
+ self.root.join("check_cache_v1")
+ }
+
+ /// Path to the registries cache, used for the lps.
+ pub fn registries_folder_path(&self) -> PathBuf {
+ self.root.join("registries")
+ }
+
+ /// Path to the dependencies cache folder.
+ pub fn deps_folder_path(&self) -> PathBuf {
+ self.root.join("deps")
+ }
+
+ /// Path to the origin data cache folder.
+ pub fn origin_data_folder_path(&self) -> PathBuf {
+ // TODO(@crowlKats): change to origin_data for 2.0
+ self.root.join("location_data")
+ }
+
+ /// File used for the upgrade checker.
+ pub fn upgrade_check_file_path(&self) -> PathBuf {
+ self.root.join("latest.txt")
+ }
+
+ /// Folder used for the npm cache.
+ pub fn npm_folder_path(&self) -> PathBuf {
+ self.root.join("npm")
+ }
+
+ /// Path used for the REPL history file.
+ pub fn repl_history_file_path(&self) -> PathBuf {
+ self.root.join("deno_history.txt")
+ }
+
+ /// Folder path used for downloading new versions of deno.
+ pub fn dl_folder_path(&self) -> PathBuf {
+ self.root.join("dl")
+ }
+}
+
+/// To avoid the poorly managed dirs crate
+#[cfg(not(windows))]
+mod dirs {
+ use std::path::PathBuf;
+
+ pub fn cache_dir() -> Option<PathBuf> {
+ if cfg!(target_os = "macos") {
+ home_dir().map(|h| h.join("Library/Caches"))
+ } else {
+ std::env::var_os("XDG_CACHE_HOME")
+ .map(PathBuf::from)
+ .or_else(|| home_dir().map(|h| h.join(".cache")))
+ }
+ }
+
+ pub fn home_dir() -> Option<PathBuf> {
+ std::env::var_os("HOME")
+ .and_then(|h| if h.is_empty() { None } else { Some(h) })
+ .or_else(|| {
+ // TODO(bartlomieju):
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ fallback()
+ }
+ })
+ .map(PathBuf::from)
+ }
+
+ // This piece of code is taken from the deprecated home_dir() function in Rust's standard library: https://github.com/rust-lang/rust/blob/master/src/libstd/sys/unix/os.rs#L579
+ // The same code is used by the dirs crate
+ unsafe fn fallback() -> Option<std::ffi::OsString> {
+ let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
+ n if n < 0 => 512_usize,
+ n => n as usize,
+ };
+ let mut buf = Vec::with_capacity(amt);
+ let mut passwd: libc::passwd = std::mem::zeroed();
+ let mut result = std::ptr::null_mut();
+ match libc::getpwuid_r(
+ libc::getuid(),
+ &mut passwd,
+ buf.as_mut_ptr(),
+ buf.capacity(),
+ &mut result,
+ ) {
+ 0 if !result.is_null() => {
+ let ptr = passwd.pw_dir as *const _;
+ let bytes = std::ffi::CStr::from_ptr(ptr).to_bytes().to_vec();
+ Some(std::os::unix::ffi::OsStringExt::from_vec(bytes))
+ }
+ _ => None,
+ }
+ }
+}
+
+/// To avoid the poorly managed dirs crate
+// Copied from
+// https://github.com/dirs-dev/dirs-sys-rs/blob/ec7cee0b3e8685573d847f0a0f60aae3d9e07fa2/src/lib.rs#L140-L164
+// MIT license. Copyright (c) 2018-2019 dirs-rs contributors
+#[cfg(windows)]
+mod dirs {
+ use std::ffi::OsString;
+ use std::os::windows::ffi::OsStringExt;
+ use std::path::PathBuf;
+ use winapi::shared::winerror;
+ use winapi::um::{combaseapi, knownfolders, shlobj, shtypes, winbase, winnt};
+
+ fn known_folder(folder_id: shtypes::REFKNOWNFOLDERID) -> Option<PathBuf> {
+ // SAFETY: winapi calls
+ unsafe {
+ let mut path_ptr: winnt::PWSTR = std::ptr::null_mut();
+ let result = shlobj::SHGetKnownFolderPath(
+ folder_id,
+ 0,
+ std::ptr::null_mut(),
+ &mut path_ptr,
+ );
+ if result == winerror::S_OK {
+ let len = winbase::lstrlenW(path_ptr) as usize;
+ let path = std::slice::from_raw_parts(path_ptr, len);
+ let ostr: OsString = OsStringExt::from_wide(path);
+ combaseapi::CoTaskMemFree(path_ptr as *mut winapi::ctypes::c_void);
+ Some(PathBuf::from(ostr))
+ } else {
+ None
+ }
+ }
+ }
+
+ pub fn cache_dir() -> Option<PathBuf> {
+ known_folder(&knownfolders::FOLDERID_LocalAppData)
+ }
+
+ pub fn home_dir() -> Option<PathBuf> {
+ known_folder(&knownfolders::FOLDERID_Profile)
+ }
+}