2023-01-02 21:00:42 +00:00
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2020-09-06 00:34:02 +00:00
2022-11-26 00:04:30 +00:00
use super ::DiskCache ;
2022-07-12 22:58:39 +00:00
2018-07-26 21:54:22 +00:00
use std ::path ::PathBuf ;
2019-06-24 16:04:06 +00:00
2019-07-17 22:15:30 +00:00
/// `DenoDir` serves as coordinator for multiple `DiskCache`s containing them
/// in single directory that can be controlled with `$DENO_DIR` env variable.
2019-04-02 01:46:40 +00:00
#[ derive(Clone) ]
2018-07-26 21:54:22 +00:00
pub struct DenoDir {
2020-06-21 03:49:27 +00:00
/// Example: /Users/rld/.deno/
2022-11-26 00:04:30 +00:00
/// Note: This is not exposed in order to encourage using re-usable methods.
root : PathBuf ,
2019-07-31 11:58:41 +00:00
/// Used by TsCompiler to cache compiler output.
pub gen_cache : DiskCache ,
2018-07-26 21:54:22 +00:00
}
impl DenoDir {
2020-05-15 14:32:52 +00:00
pub fn new ( maybe_custom_root : Option < PathBuf > ) -> std ::io ::Result < Self > {
let root : PathBuf = if let Some ( root ) = maybe_custom_root {
2022-02-03 13:08:17 +00:00
root
2020-07-13 16:24:54 +00:00
} 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 " )
2020-05-15 14:32:52 +00:00
} else {
2020-07-13 16:24:54 +00:00
panic! ( " Could not set the Deno root directory " )
2020-05-15 14:32:52 +00:00
} ;
2022-02-03 13:08:17 +00:00
let root = if root . is_absolute ( ) {
root
} else {
std ::env ::current_dir ( ) ? . join ( root )
} ;
2020-05-15 14:32:52 +00:00
assert! ( root . is_absolute ( ) ) ;
2019-07-31 11:58:41 +00:00
let gen_path = root . join ( " gen " ) ;
2019-04-29 14:58:31 +00:00
2018-11-05 06:21:21 +00:00
let deno_dir = Self {
2018-08-14 20:50:53 +00:00
root ,
2019-07-31 11:58:41 +00:00
gen_cache : DiskCache ::new ( & gen_path ) ,
2018-08-14 20:50:53 +00:00
} ;
2020-05-24 17:20:40 +00:00
deno_dir . gen_cache . ensure_dir_exists ( & gen_path ) ? ;
2019-01-18 04:39:06 +00:00
2018-07-26 21:54:22 +00:00
Ok ( deno_dir )
}
2022-04-20 02:14:00 +00:00
2022-11-26 00:04:30 +00:00
/// The root directory of the DENO_DIR for display purposes only.
pub fn root_path_for_display ( & self ) -> std ::path ::Display {
self . root . display ( )
}
2022-04-20 02:14:00 +00:00
/// 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 " )
}
2022-07-12 22:58:39 +00:00
2022-08-22 16:14:59 +00:00
/// 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 " )
}
2022-10-01 10:15:56 +00:00
/// 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 " )
}
2022-07-19 15:58:18 +00:00
/// Path for the cache used for type checking.
2022-07-12 22:58:39 +00:00
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 " )
}
2022-11-26 00:04:30 +00:00
/// 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 " )
}
2019-07-17 22:15:30 +00:00
}
2020-06-21 03:49:27 +00:00
/// 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 ) } )
2022-06-25 22:13:24 +00:00
. or_else ( | | {
// TODO(bartlomieju):
#[ allow(clippy::undocumented_unsafe_blocks) ]
unsafe {
fallback ( )
}
} )
2020-06-21 03:49:27 +00:00
. map ( PathBuf ::from )
}
2020-07-13 16:24:54 +00:00
// 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 ) {
2020-11-27 19:47:35 +00:00
n if n < 0 = > 512_ usize ,
2020-07-13 16:24:54 +00:00
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 ,
}
}
2020-06-21 03:49:27 +00:00
}
/// 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 > {
2022-07-15 16:30:25 +00:00
// SAFETY: winapi calls
2020-06-21 03:49:27 +00:00
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 )
}
}