|
1 |
| -use derive_more::{Display, Error}; |
2 |
| -use miette::Diagnostic; |
3 |
| -use std::{ |
4 |
| - fs::{self, OpenOptions}, |
5 |
| - io::{self, Write}, |
6 |
| - path::{Path, PathBuf}, |
7 |
| -}; |
| 1 | +mod ensure_file; |
| 2 | +mod symlink_dir; |
8 | 3 |
|
9 |
| -pub mod file_mode { |
10 |
| - /// Bit mask to filter executable bits (`--x--x--x`). |
11 |
| - pub const EXEC_MASK: u32 = 0b001_001_001; |
| 4 | +pub use ensure_file::*; |
| 5 | +pub use symlink_dir::*; |
12 | 6 |
|
13 |
| - /// All can read and execute, but only owner can write (`rwxr-xr-x`). |
14 |
| - pub const EXEC_MODE: u32 = 0b111_101_101; |
15 |
| - |
16 |
| - /// Whether a file mode has all executable bits. |
17 |
| - pub fn is_all_exec(mode: u32) -> bool { |
18 |
| - mode & EXEC_MASK == EXEC_MASK |
19 |
| - } |
20 |
| -} |
21 |
| - |
22 |
| -/// Create a symlink to a directory. |
23 |
| -/// |
24 |
| -/// The `link` path will be a symbolic link pointing to `original`. |
25 |
| -pub fn symlink_dir(original: &Path, link: &Path) -> io::Result<()> { |
26 |
| - #[cfg(unix)] |
27 |
| - return std::os::unix::fs::symlink(original, link); |
28 |
| - #[cfg(windows)] |
29 |
| - return junction::create(original, link); // junctions instead of symlinks because symlinks may require elevated privileges. |
30 |
| -} |
31 |
| - |
32 |
| -/// Error type of [`ensure_file`]. |
33 |
| -#[derive(Debug, Display, Error, Diagnostic)] |
34 |
| -pub enum EnsureFileError { |
35 |
| - #[display("Failed to create the parent directory at {parent_dir:?}: {error}")] |
36 |
| - CreateDir { |
37 |
| - parent_dir: PathBuf, |
38 |
| - #[error(source)] |
39 |
| - error: io::Error, |
40 |
| - }, |
41 |
| - #[display("Failed to create file at {file_path:?}: {error}")] |
42 |
| - CreateFile { |
43 |
| - file_path: PathBuf, |
44 |
| - #[error(source)] |
45 |
| - error: io::Error, |
46 |
| - }, |
47 |
| - #[display("Failed to write to file at {file_path:?}: {error}")] |
48 |
| - WriteFile { |
49 |
| - file_path: PathBuf, |
50 |
| - #[error(source)] |
51 |
| - error: io::Error, |
52 |
| - }, |
53 |
| -} |
54 |
| - |
55 |
| -/// Write `content` to `file_path` unless it already exists. |
56 |
| -/// |
57 |
| -/// Ancestor directories will be created if they don't already exist. |
58 |
| -pub fn ensure_file( |
59 |
| - file_path: &Path, |
60 |
| - content: &[u8], |
61 |
| - #[cfg_attr(windows, allow(unused))] mode: Option<u32>, |
62 |
| -) -> Result<(), EnsureFileError> { |
63 |
| - if file_path.exists() { |
64 |
| - return Ok(()); |
65 |
| - } |
66 |
| - |
67 |
| - let parent_dir = file_path.parent().unwrap(); |
68 |
| - fs::create_dir_all(parent_dir).map_err(|error| EnsureFileError::CreateDir { |
69 |
| - parent_dir: parent_dir.to_path_buf(), |
70 |
| - error, |
71 |
| - })?; |
72 |
| - |
73 |
| - let mut options = OpenOptions::new(); |
74 |
| - options.write(true).create(true); |
75 |
| - |
76 |
| - #[cfg(unix)] |
77 |
| - { |
78 |
| - use std::os::unix::fs::OpenOptionsExt; |
79 |
| - if let Some(mode) = mode { |
80 |
| - options.mode(mode); |
81 |
| - } |
82 |
| - } |
83 |
| - |
84 |
| - options |
85 |
| - .open(file_path) |
86 |
| - .map_err(|error| EnsureFileError::CreateFile { file_path: file_path.to_path_buf(), error })? |
87 |
| - .write_all(content) |
88 |
| - .map_err(|error| EnsureFileError::WriteFile { file_path: file_path.to_path_buf(), error }) |
89 |
| -} |
90 |
| - |
91 |
| -/// Set file mode to 777 on POSIX platforms such as Linux or macOS, |
92 |
| -/// or do nothing on Windows. |
93 |
| -#[cfg_attr(windows, allow(unused))] |
94 |
| -pub fn make_file_executable(file: &std::fs::File) -> io::Result<()> { |
95 |
| - #[cfg(unix)] |
96 |
| - return { |
97 |
| - use std::{ |
98 |
| - fs::Permissions, |
99 |
| - os::unix::fs::{MetadataExt, PermissionsExt}, |
100 |
| - }; |
101 |
| - let mode = file.metadata()?.mode(); |
102 |
| - let mode = mode | file_mode::EXEC_MASK; |
103 |
| - let permissions = Permissions::from_mode(mode); |
104 |
| - file.set_permissions(permissions) |
105 |
| - }; |
106 |
| - |
107 |
| - #[cfg(windows)] |
108 |
| - return Ok(()); |
109 |
| -} |
| 7 | +pub mod file_mode; |
0 commit comments