From fa8650e6e57d3aae318fd6f1102893e982fef2e5 Mon Sep 17 00:00:00 2001 From: Marek Kaput Date: Mon, 30 Oct 2023 18:18:13 +0100 Subject: [PATCH] Add `AsyncFileLockGuard` This data structure will be later used in Tokio-based code which writes to the file protected by this guard. Signed-off-by: Marek Kaput commit-id:ebda97d6 --- scarb/src/flock.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/scarb/src/flock.rs b/scarb/src/flock.rs index d5502b757..544b0d201 100644 --- a/scarb/src/flock.rs +++ b/scarb/src/flock.rs @@ -6,6 +6,7 @@ use std::{fmt, io}; use anyhow::{ensure, Context, Result}; use camino::{Utf8Path, Utf8PathBuf}; +use fs4::tokio::AsyncFileExt; use fs4::{lock_contended_error, FileExt}; use tokio::sync::Mutex; @@ -51,6 +52,14 @@ impl FileLockGuard { self.path = to; Ok(self) } + + pub fn into_async(mut self) -> AsyncFileLockGuard { + AsyncFileLockGuard { + file: self.file.take().map(tokio::fs::File::from_std), + path: std::mem::take(&mut self.path), + lock_kind: self.lock_kind, + } + } } impl Deref for FileLockGuard { @@ -75,6 +84,56 @@ impl Drop for FileLockGuard { } } +#[derive(Debug)] +pub struct AsyncFileLockGuard { + file: Option, + path: Utf8PathBuf, + lock_kind: FileLockKind, +} + +impl AsyncFileLockGuard { + pub fn path(&self) -> &Utf8Path { + self.path.as_path() + } + + pub fn lock_kind(&self) -> FileLockKind { + self.lock_kind + } + + pub async fn into_sync(mut self) -> FileLockGuard { + FileLockGuard { + file: match self.file.take() { + None => None, + Some(file) => Some(file.into_std().await), + }, + path: std::mem::take(&mut self.path), + lock_kind: self.lock_kind, + } + } +} + +impl Deref for AsyncFileLockGuard { + type Target = tokio::fs::File; + + fn deref(&self) -> &Self::Target { + self.file.as_ref().unwrap() + } +} + +impl DerefMut for AsyncFileLockGuard { + fn deref_mut(&mut self) -> &mut Self::Target { + self.file.as_mut().unwrap() + } +} + +impl Drop for AsyncFileLockGuard { + fn drop(&mut self) { + if let Some(file) = self.file.take() { + let _ = file.unlock(); + } + } +} + /// An exclusive lock over a global entity identified by a path within a [`Filesystem`]. pub struct AdvisoryLock<'f> { path: Utf8PathBuf,