diff options
author | Nathan Whitaker <17734409+nathanwhit@users.noreply.github.com> | 2024-06-28 17:18:21 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-28 17:18:21 -0700 |
commit | bc8a0e6e68547cf07a246b8b6c886de155dc8282 (patch) | |
tree | a3540b01218c4674c399eb770c0f08e5ba594793 /cli/args/lockfile.rs | |
parent | 2ddae872f956ddd84656a302aa5f6b752f6a6ab5 (diff) |
refactor(cli): Create wrapper around `deno_lockfile::Lockfile` (#24366)
As suggested in
https://github.com/denoland/deno/pull/24355#discussion_r1657875422.
I wasn't able to hide the mutex stuff as much as I'd like (ended up just
adding an escape hatch `inner()` method that locks the inner mutex),
because you can't return references to the inner fields through a mutex.
This is mostly motivated by the frozen lockfile changes
Diffstat (limited to 'cli/args/lockfile.rs')
-rw-r--r-- | cli/args/lockfile.rs | 194 |
1 files changed, 126 insertions, 68 deletions
diff --git a/cli/args/lockfile.rs b/cli/args/lockfile.rs index 7e59853b0..555261336 100644 --- a/cli/args/lockfile.rs +++ b/cli/args/lockfile.rs @@ -4,6 +4,8 @@ use std::path::PathBuf; use deno_core::anyhow::Context; use deno_core::error::AnyError; +use deno_core::parking_lot::Mutex; +use deno_core::parking_lot::MutexGuard; use deno_runtime::deno_node::PackageJson; use crate::args::ConfigFile; @@ -11,81 +13,137 @@ use crate::cache; use crate::util::fs::atomic_write_file_with_retries; use crate::Flags; -use super::DenoSubcommand; -use super::InstallFlags; -use super::InstallKind; - -pub use deno_lockfile::Lockfile; - -pub fn discover( - flags: &Flags, - maybe_config_file: Option<&ConfigFile>, - maybe_package_json: Option<&PackageJson>, -) -> Result<Option<Lockfile>, AnyError> { - if flags.no_lock - || matches!( - flags.subcommand, - DenoSubcommand::Install(InstallFlags { - kind: InstallKind::Global(..), - .. - }) | DenoSubcommand::Uninstall(_) +use crate::args::DenoSubcommand; +use crate::args::InstallFlags; +use crate::args::InstallKind; + +use deno_lockfile::Lockfile; + +#[derive(Debug)] +pub struct CliLockfile { + lockfile: Mutex<Lockfile>, + pub filename: PathBuf, +} + +pub struct Guard<'a, T> { + guard: MutexGuard<'a, T>, +} + +impl<'a, T> std::ops::Deref for Guard<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.guard + } +} + +impl<'a, T> std::ops::DerefMut for Guard<'a, T> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.guard + } +} + +impl CliLockfile { + pub fn new(lockfile: Lockfile) -> Self { + let filename = lockfile.filename.clone(); + Self { + lockfile: Mutex::new(lockfile), + filename, + } + } + + /// Get the inner deno_lockfile::Lockfile. + pub fn lock(&self) -> Guard<Lockfile> { + Guard { + guard: self.lockfile.lock(), + } + } + + pub fn set_workspace_config( + &self, + options: deno_lockfile::SetWorkspaceConfigOptions, + ) { + self.lockfile.lock().set_workspace_config(options); + } + + pub fn overwrite(&self) -> bool { + self.lockfile.lock().overwrite + } + + pub fn write_if_changed(&self) -> Result<(), AnyError> { + let mut lockfile = self.lockfile.lock(); + let Some(bytes) = lockfile.resolve_write_bytes() else { + return Ok(()); // nothing to do + }; + // do an atomic write to reduce the chance of multiple deno + // processes corrupting the file + atomic_write_file_with_retries( + &lockfile.filename, + bytes, + cache::CACHE_PERM, ) - { - return Ok(None); + .context("Failed writing lockfile.")?; + lockfile.has_content_changed = false; + Ok(()) } - let filename = match flags.lock { - Some(ref lock) => PathBuf::from(lock), - None => match maybe_config_file { - Some(config_file) => { - if config_file.specifier.scheme() == "file" { - match config_file.resolve_lockfile_path()? { - Some(path) => path, - None => return Ok(None), + pub fn discover( + flags: &Flags, + maybe_config_file: Option<&ConfigFile>, + maybe_package_json: Option<&PackageJson>, + ) -> Result<Option<CliLockfile>, AnyError> { + if flags.no_lock + || matches!( + flags.subcommand, + DenoSubcommand::Install(InstallFlags { + kind: InstallKind::Global(..), + .. + }) | DenoSubcommand::Uninstall(_) + ) + { + return Ok(None); + } + + let filename = match flags.lock { + Some(ref lock) => PathBuf::from(lock), + None => match maybe_config_file { + Some(config_file) => { + if config_file.specifier.scheme() == "file" { + match config_file.resolve_lockfile_path()? { + Some(path) => path, + None => return Ok(None), + } + } else { + return Ok(None); } - } else { - return Ok(None); } - } - None => match maybe_package_json { - Some(package_json) => { - package_json.path.parent().unwrap().join("deno.lock") - } - None => return Ok(None), + None => match maybe_package_json { + Some(package_json) => { + package_json.path.parent().unwrap().join("deno.lock") + } + None => return Ok(None), + }, }, - }, - }; - - let lockfile = if flags.lock_write { - Lockfile::new_empty(filename, true) - } else { - read_lockfile_at_path(filename)? - }; - Ok(Some(lockfile)) -} + }; -pub fn read_lockfile_at_path(filename: PathBuf) -> Result<Lockfile, AnyError> { - match std::fs::read_to_string(&filename) { - Ok(text) => Ok(Lockfile::with_lockfile_content(filename, &text, false)?), - Err(err) if err.kind() == std::io::ErrorKind::NotFound => { - Ok(Lockfile::new_empty(filename, false)) + let lockfile = if flags.lock_write { + CliLockfile::new(Lockfile::new_empty(filename, true)) + } else { + Self::read_from_path(filename)? + }; + Ok(Some(lockfile)) + } + pub fn read_from_path(filename: PathBuf) -> Result<CliLockfile, AnyError> { + match std::fs::read_to_string(&filename) { + Ok(text) => Ok(CliLockfile::new(Lockfile::with_lockfile_content( + filename, &text, false, + )?)), + Err(err) if err.kind() == std::io::ErrorKind::NotFound => { + Ok(CliLockfile::new(Lockfile::new_empty(filename, false))) + } + Err(err) => Err(err).with_context(|| { + format!("Failed reading lockfile '{}'", filename.display()) + }), } - Err(err) => Err(err).with_context(|| { - format!("Failed reading lockfile '{}'", filename.display()) - }), } } - -pub fn write_lockfile_if_has_changes( - lockfile: &mut Lockfile, -) -> Result<(), AnyError> { - let Some(bytes) = lockfile.resolve_write_bytes() else { - return Ok(()); // nothing to do - }; - // do an atomic write to reduce the chance of multiple deno - // processes corrupting the file - atomic_write_file_with_retries(&lockfile.filename, bytes, cache::CACHE_PERM) - .context("Failed writing lockfile.")?; - lockfile.has_content_changed = false; - Ok(()) -} |