diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2022-11-25 19:04:30 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-26 00:04:30 +0000 |
commit | 0c0af67f89b610eb61e4f66a5dbf665474aa9383 (patch) | |
tree | b2da2181d6ce10395da176ca8ac352345fc65fca /cli/cache/deno_dir.rs | |
parent | e0dd275935c49f5b5b844123d621c5dea1761983 (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.rs | 218 |
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) + } +} |