summaryrefslogtreecommitdiff
path: root/cli/args/lockfile.rs
diff options
context:
space:
mode:
authorNathan Whitaker <17734409+nathanwhit@users.noreply.github.com>2024-06-28 17:18:21 -0700
committerGitHub <noreply@github.com>2024-06-28 17:18:21 -0700
commitbc8a0e6e68547cf07a246b8b6c886de155dc8282 (patch)
treea3540b01218c4674c399eb770c0f08e5ba594793 /cli/args/lockfile.rs
parent2ddae872f956ddd84656a302aa5f6b752f6a6ab5 (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.rs194
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(())
-}