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

Configure Feed

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

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