Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

gleam / compiler-cli / src / build_lock.rs
5.1 kB 155 lines
1// SPDX-License-Identifier: Apache-2.0 2// SPDX-FileCopyrightText: 2022 The Gleam contributors 3 4use camino::Utf8PathBuf; 5use gleam_core::{ 6 Error, Result, 7 build::{Mode, Target, Telemetry}, 8 error::{FileIoAction, FileKind}, 9 paths::ProjectPaths, 10}; 11use strum::IntoEnumIterator; 12 13#[derive(Debug)] 14pub(crate) struct BuildLock { 15 directory: Utf8PathBuf, 16 filename: String, 17} 18 19impl BuildLock { 20 /// Lock the build directory for the specified mode and target. 21 pub fn new_target(paths: &ProjectPaths, mode: Mode, target: Target) -> Result<Self> { 22 let directory = paths.build_directory(); 23 crate::fs::mkdir(&directory)?; 24 let target = match target { 25 Target::Erlang => "erlang", 26 Target::JavaScript => "javascript", 27 }; 28 Ok(Self { 29 directory, 30 filename: format!("gleam-{mode}-{target}.lock"), 31 }) 32 } 33 34 /// Lock the packages directory. 35 pub fn new_packages(paths: &ProjectPaths) -> Result<Self> { 36 let directory = paths.build_packages_directory(); 37 crate::fs::mkdir(&directory)?; 38 Ok(Self { 39 directory, 40 filename: "gleam.lock".to_string(), 41 }) 42 } 43 44 /// Construct the lock file path 45 pub fn lock_path(&self) -> Utf8PathBuf { 46 self.directory.join(&self.filename) 47 } 48 49 /// Lock the directory specified by the lock 50 pub fn lock<Telem: Telemetry + ?Sized>(&self, telemetry: &Telem) -> Result<Guard> { 51 let lock_path = self.lock_path(); 52 tracing::debug!(path=?lock_path, "locking_directory"); 53 54 crate::fs::mkdir(&self.directory)?; 55 56 let mut file = fslock::LockFile::open(lock_path.as_str()).map_err(|e| Error::FileIo { 57 kind: FileKind::File, 58 path: lock_path.clone(), 59 action: FileIoAction::Create, 60 err: Some(e.to_string()), 61 })?; 62 63 let lock_error = |error: fslock::Error| Error::FileIo { 64 kind: FileKind::File, 65 action: FileIoAction::Lock, 66 path: lock_path.clone(), 67 err: Some(error.to_string()), 68 }; 69 70 if !file.try_lock_with_pid().map_err(lock_error)? { 71 telemetry.waiting_for_build_directory_lock(); 72 file.lock_with_pid().map_err(lock_error)? 73 } 74 75 Ok(Guard(file)) 76 } 77 78 /// Lock all build directories. Does not lock the packages directory. 79 pub fn lock_all_build<Telem: Telemetry>( 80 paths: &ProjectPaths, 81 telemetry: &Telem, 82 ) -> Result<Vec<Guard>> { 83 let mut locks = vec![]; 84 for mode in Mode::iter() { 85 for target in Target::iter() { 86 locks.push(Self::new_target(paths, mode, target)?.lock(telemetry)?); 87 } 88 } 89 90 Ok(locks) 91 } 92} 93 94#[derive(Debug)] 95pub(crate) struct Guard( 96 // False positive. This is used in `drop`. Presumably the lint error is a 97 // bug in clippy. 98 #[allow(dead_code)] fslock::LockFile, 99); 100 101#[test] 102fn locking_global() { 103 let paths = crate::project_paths_at_current_directory_without_toml(); 104 let lock = BuildLock::new_packages(&paths).expect("make lock"); 105 let _guard1: Guard = lock.lock(&gleam_core::build::NullTelemetry).unwrap(); 106 println!("Locked!") 107} 108 109#[test] 110fn locking_dev_erlang() { 111 let paths = crate::project_paths_at_current_directory_without_toml(); 112 let lock = BuildLock::new_target(&paths, Mode::Dev, Target::Erlang).expect("make lock"); 113 let _guard1: Guard = lock.lock(&gleam_core::build::NullTelemetry).unwrap(); 114 println!("Locked!") 115} 116 117#[test] 118fn locking_prod_erlang() { 119 let paths = crate::project_paths_at_current_directory_without_toml(); 120 let lock = BuildLock::new_target(&paths, Mode::Prod, Target::Erlang).expect("make lock"); 121 let _guard1: Guard = lock.lock(&gleam_core::build::NullTelemetry).unwrap(); 122 println!("Locked!") 123} 124 125#[test] 126fn locking_lsp_erlang() { 127 let paths = crate::project_paths_at_current_directory_without_toml(); 128 let lock = BuildLock::new_target(&paths, Mode::Lsp, Target::Erlang).expect("make lock"); 129 let _guard1: Guard = lock.lock(&gleam_core::build::NullTelemetry).unwrap(); 130 println!("Locked!") 131} 132 133#[test] 134fn locking_dev_javascript() { 135 let paths = crate::project_paths_at_current_directory_without_toml(); 136 let lock = BuildLock::new_target(&paths, Mode::Dev, Target::JavaScript).expect("make lock"); 137 let _guard1: Guard = lock.lock(&gleam_core::build::NullTelemetry).unwrap(); 138 println!("Locked!") 139} 140 141#[test] 142fn locking_prod_javascript() { 143 let paths = crate::project_paths_at_current_directory_without_toml(); 144 let lock = BuildLock::new_target(&paths, Mode::Prod, Target::JavaScript).expect("make lock"); 145 let _guard1: Guard = lock.lock(&gleam_core::build::NullTelemetry).unwrap(); 146 println!("Locked!") 147} 148 149#[test] 150fn locking_lsp_javascript() { 151 let paths = crate::project_paths_at_current_directory_without_toml(); 152 let lock = BuildLock::new_target(&paths, Mode::Lsp, Target::JavaScript).expect("make lock"); 153 let _guard1: Guard = lock.lock(&gleam_core::build::NullTelemetry).unwrap(); 154 println!("Locked!") 155}