diff --git a/Cargo.lock b/Cargo.lock index a216312..0dc6b78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -219,19 +219,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown", - "lock_api", - "once_cell", - "parking_lot_core", -] - [[package]] name = "der" version = "0.7.9" @@ -330,18 +317,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "faster-hex" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" - -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - [[package]] name = "ff" version = "0.13.0" @@ -361,6 +336,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs4" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c6b3bd49c37d2aa3f3f2220233b29a7cd23f79d1fe70e5337d25fb390793de" +dependencies = [ + "rustix", + "windows-sys", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -398,82 +383,6 @@ dependencies = [ "url", ] -[[package]] -name = "gix-features" -version = "0.38.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac7045ac9fe5f9c727f38799d002a7ed3583cd777e3322a7c4b43e3cf437dc69" -dependencies = [ - "gix-hash", - "gix-trace", - "gix-utils", - "libc", -] - -[[package]] -name = "gix-fs" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3338ff92a2164f5209f185ec0cd316f571a72676bb01d27e22f2867ba69f77a" -dependencies = [ - "fastrand", - "gix-features", - "gix-utils", -] - -[[package]] -name = "gix-hash" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93d7df7366121b5018f947a04d37f034717e113dcf9ccd85c34b58e57a74d5e" -dependencies = [ - "faster-hex", - "thiserror", -] - -[[package]] -name = "gix-lock" -version = "14.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bc7fe297f1f4614774989c00ec8b1add59571dc9b024b4c00acb7dedd4e19d" -dependencies = [ - "gix-tempfile", - "gix-utils", - "thiserror", -] - -[[package]] -name = "gix-tempfile" -version = "14.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3b0e276cd08eb2a22e9f286a4f13a222a01be2defafa8621367515375644b99" -dependencies = [ - "dashmap", - "gix-fs", - "libc", - "once_cell", - "parking_lot", - "signal-hook", - "signal-hook-registry", - "tempfile", -] - -[[package]] -name = "gix-trace" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f924267408915fddcd558e3f37295cc7d6a3e50f8bd8b606cee0808c3915157e" - -[[package]] -name = "gix-utils" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35192df7fd0fa112263bad8021e2df7167df4cc2a6e6d15892e1e55621d3d4dc" -dependencies = [ - "fastrand", - "unicode-normalization", -] - [[package]] name = "group" version = "0.13.0" @@ -626,16 +535,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "log" version = "0.4.22" @@ -783,29 +682,6 @@ dependencies = [ "sha2", ] -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - [[package]] name = "pathdiff" version = "0.2.1" @@ -902,9 +778,8 @@ dependencies = [ "clap", "config", "env_logger", + "fs4", "git2", - "gix-lock", - "gix-tempfile", "home", "log", "pretty_assertions", @@ -954,15 +829,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "redox_syscall" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" -dependencies = [ - "bitflags", -] - [[package]] name = "regex-lite" version = "0.1.6" @@ -1013,12 +879,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "sec1" version = "0.7.3" @@ -1073,25 +933,6 @@ dependencies = [ "digest", ] -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - [[package]] name = "signature" version = "2.2.0" @@ -1188,18 +1029,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand", - "rustix", - "windows-sys", -] - [[package]] name = "thiserror" version = "1.0.62" diff --git a/Cargo.toml b/Cargo.toml index fe08a28..781824c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "protofetch" version = "0.1.7" edition = "2021" -rust-version = "1.74" +rust-version = "1.75" license = "Apache-2.0" description = "A source dependency management tool for Protobuf." homepage = "https://github.com/coralogix/protofetch" @@ -21,9 +21,8 @@ anyhow = "1.0.86" clap = { version = "4.5.9", features = ["derive"] } config = { version = "0.14.0", default-features = false, features = ["toml"] } env_logger = { version = "0.11.3", default-features = false, features = ["auto-color"] } +fs4 = "0.9.1" git2 = ">=0.18.0, <0.20.0" -gix-lock = { version = "14.0.0" } -gix-tempfile = { version = "14.0.0", features = ["signals"] } home = "0.5.9" log = "0.4.22" regex-lite = "0.1.6" diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 07e2d0e..544cdbb 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -2,4 +2,4 @@ # The default profile includes rustc, rust-std, cargo, rust-docs, rustfmt and clippy. # https://rust-lang.github.io/rustup/concepts/profiles.html profile = "default" -channel = "1.79.0" +channel = "1.80.1" diff --git a/src/flock.rs b/src/flock.rs new file mode 100644 index 0000000..8fb5077 --- /dev/null +++ b/src/flock.rs @@ -0,0 +1,39 @@ +use std::{ + fs::File, + path::Path, + time::{Duration, Instant}, +}; + +use fs4::fs_std::FileExt; +use log::debug; +use thiserror::Error; + +pub struct FileLock { + _file: File, +} + +#[derive(Error, Debug)] +#[error(transparent)] +pub struct Error(#[from] std::io::Error); + +impl FileLock { + pub fn new(path: &Path) -> Result { + let file = File::create(path)?; + let start = Instant::now(); + loop { + match file.try_lock_exclusive() { + Ok(_) => { + return Ok(Self { _file: file }); + } + Err(error) + if error.raw_os_error() == fs4::lock_contended_error().raw_os_error() + && start.elapsed().as_secs() < 300 => + { + debug!("Failed to acquire a lock on {}, retrying", path.display()); + std::thread::sleep(Duration::from_secs(1)); + } + Err(error) => return Err(error.into()), + } + } + } +} diff --git a/src/git/cache.rs b/src/git/cache.rs index b879a63..9e39c78 100644 --- a/src/git/cache.rs +++ b/src/git/cache.rs @@ -1,18 +1,15 @@ -use std::{ - path::{Path, PathBuf}, - time::{Duration, Instant}, -}; +use std::path::{Path, PathBuf}; use git2::{ cert::Cert, AutotagOption, CertificateCheckStatus, Config, Cred, CredentialType, FetchOptions, RemoteCallbacks, Repository, }; -use gix_lock::Marker; use log::{debug, info, trace}; use ssh_key::{known_hosts::HostPatterns, KnownHosts}; use thiserror::Error; use crate::{ + flock::FileLock, git::repository::ProtoGitRepository, model::protofetch::{Coordinate, Protocol}, }; @@ -25,7 +22,7 @@ pub struct ProtofetchGitCache { worktrees: PathBuf, git_config: Config, default_protocol: Protocol, - _lock: Marker, + _lock: FileLock, } #[derive(Error, Debug)] @@ -35,7 +32,7 @@ pub enum CacheError { #[error("Cache location {location} does not exist")] BadLocation { location: String }, #[error("Cache lock cannot be acquired")] - Lock(#[from] gix_lock::acquire::Error), + Lock(#[from] crate::flock::Error), #[error("IO error: {0}")] IO(#[from] std::io::Error), } @@ -56,7 +53,6 @@ impl ProtofetchGitCache { std::fs::create_dir_all(&location)?; } - gix_lock::tempfile::signal::setup(Default::default()); let lock = Self::acquire_lock(&location)?; let worktrees = location.join(WORKTREES_DIR); @@ -99,29 +95,15 @@ impl ProtofetchGitCache { &self.worktrees } - fn acquire_lock(location: &Path) -> Result { - use gix_lock::acquire::Fail; + fn acquire_lock(location: &Path) -> Result { + let location = location.join(".lock"); debug!( "Acquiring a lock on the cache location: {}", location.display() ); - let start = Instant::now(); - loop { - match Marker::acquire_to_hold_resource(location, Fail::Immediately, None) { - Ok(lock) => { - info!("Acquired a lock on the cache location"); - return Ok(lock); - } - Err(error) => { - if start.elapsed() < Duration::from_secs(300) { - debug!("Failed to acquire a lock on the cache location, retrying"); - std::thread::sleep(Duration::from_secs(1)); - } else { - return Err(error.into()); - } - } - } - } + let lock = FileLock::new(&location)?; + info!("Acquired a lock on the cache location"); + Ok(lock) } fn open_entry(&self, path: &Path, url: &str) -> Result { diff --git a/src/lib.rs b/src/lib.rs index 03c5dad..e4de707 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ mod cache; mod cli; mod config; mod fetch; +mod flock; mod git; mod model; mod proto;