1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
//! Simple library for cleaning up non-RIAA resources using RIAA. //! //! A function that needs to clean up resources automatically can create an //! AutoCleanup object that will clean up those resources automatically. //! //! ``` //! use std::path::Path; //! use autocleanup::AutoCleanup; //! //! fn do_something() -> Result<(), std::io::Error> { //! let mut ac = AutoCleanup::new(); //! ac.push_file("/tmp/foo.sock"); //! //! // .. do things .. //! //! Ok(()) //! // /tmp/foo.sock will automatically be removed as the function //! // returns. //! } //! ``` //! //! Be mindful of the [`Drop`] trait caveats; for instance calling //! [`std::process::exit()`] will cause Drop traits not to run. //! //! Because the cleanup occurs at Drop there's no error handling for failed //! cleanups -- errors will be silently ignored. //! //! [`std::process::exit()`]: https://doc.rust-lang.org/std/process/fn.exit.html //! [`Drop`]: https://doc.rust-lang.org/std/ops/trait.Drop.html use std::path::{Path, PathBuf}; /// Representation of a cleanup node. pub enum Item { File(PathBuf), Dir(PathBuf) } pub struct AutoCleanup { items: Vec<Item> } impl AutoCleanup { /// Create a new autocleanup object. pub fn new() -> Self { AutoCleanup{ items: Vec::new() } } pub fn push(&mut self, item: Item) { self.items.push(item); } /// Push a file on to the list of objects to automatically clean up when the /// AutoClean object goes out of scope. pub fn push_file<P: AsRef<Path>>(&mut self, fname: P) { self.items.push(Item::File(fname.as_ref().to_path_buf())); } /// Push a directory on to the list of objects to automatically clean up when /// the AutoClean object goes out of scope. /// The removal operation currently does not remove items contained with it. /// It may be in the future be changed to do so. pub fn push_dir<P: AsRef<Path>>(&mut self, dname: P) { self.items.push(Item::Dir(dname.as_ref().to_path_buf())); } } impl Drop for AutoCleanup { /// Drop implementations don't have a good way to handle errors, so any /// errors are silently ignored. fn drop(&mut self) { for n in self.items.iter().rev() { match n { Item::File(p) => { let _ = std::fs::remove_file(p); } Item::Dir(p) => { let _ = std::fs::remove_dir(p); } } } } } #[test] fn test() { let mut ac = AutoCleanup::new(); ac.push_file("/nonexistent"); } // vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :