just playing with tangled
at tmp-tutorial 72 lines 2.3 kB view raw
1// Copyright 2020 The Jujutsu Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15use std::fs::{File, OpenOptions}; 16use std::path::PathBuf; 17use std::time::Duration; 18 19use backoff::{retry, ExponentialBackoff}; 20use tracing::instrument; 21 22pub struct FileLock { 23 path: PathBuf, 24 _file: File, 25} 26 27impl FileLock { 28 pub fn lock(path: PathBuf) -> FileLock { 29 let mut options = OpenOptions::new(); 30 options.create_new(true); 31 options.write(true); 32 let try_write_lock_file = || match options.open(&path) { 33 Ok(file) => Ok(FileLock { 34 path: path.clone(), 35 _file: file, 36 }), 37 Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => { 38 Err(backoff::Error::Transient { 39 err, 40 retry_after: None, 41 }) 42 } 43 Err(err) if cfg!(windows) && err.kind() == std::io::ErrorKind::PermissionDenied => { 44 Err(backoff::Error::Transient { 45 err, 46 retry_after: None, 47 }) 48 } 49 Err(err) => Err(backoff::Error::Permanent(err)), 50 }; 51 let backoff = ExponentialBackoff { 52 initial_interval: Duration::from_millis(1), 53 max_elapsed_time: Some(Duration::from_secs(10)), 54 ..Default::default() 55 }; 56 match retry(backoff, try_write_lock_file) { 57 Err(err) => panic!( 58 "failed to create lock file {}: {}", 59 path.to_string_lossy(), 60 err 61 ), 62 Ok(file_lock) => file_lock, 63 } 64 } 65} 66 67impl Drop for FileLock { 68 #[instrument(skip_all)] 69 fn drop(&mut self) { 70 std::fs::remove_file(&self.path).expect("failed to delete lock file"); 71 } 72}