-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: divide pacquet-fs into multiple files (#214)
- Loading branch information
Showing
5 changed files
with
115 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
use derive_more::{Display, Error}; | ||
use miette::Diagnostic; | ||
use std::{ | ||
fs::{self, OpenOptions}, | ||
io::{self, Write}, | ||
path::{Path, PathBuf}, | ||
}; | ||
|
||
/// Error type of [`ensure_file`]. | ||
#[derive(Debug, Display, Error, Diagnostic)] | ||
pub enum EnsureFileError { | ||
#[display("Failed to create the parent directory at {parent_dir:?}: {error}")] | ||
CreateDir { | ||
parent_dir: PathBuf, | ||
#[error(source)] | ||
error: io::Error, | ||
}, | ||
#[display("Failed to create file at {file_path:?}: {error}")] | ||
CreateFile { | ||
file_path: PathBuf, | ||
#[error(source)] | ||
error: io::Error, | ||
}, | ||
#[display("Failed to write to file at {file_path:?}: {error}")] | ||
WriteFile { | ||
file_path: PathBuf, | ||
#[error(source)] | ||
error: io::Error, | ||
}, | ||
} | ||
|
||
/// Write `content` to `file_path` unless it already exists. | ||
/// | ||
/// Ancestor directories will be created if they don't already exist. | ||
pub fn ensure_file( | ||
file_path: &Path, | ||
content: &[u8], | ||
#[cfg_attr(windows, allow(unused))] mode: Option<u32>, | ||
) -> Result<(), EnsureFileError> { | ||
if file_path.exists() { | ||
return Ok(()); | ||
} | ||
|
||
let parent_dir = file_path.parent().unwrap(); | ||
fs::create_dir_all(parent_dir).map_err(|error| EnsureFileError::CreateDir { | ||
parent_dir: parent_dir.to_path_buf(), | ||
error, | ||
})?; | ||
|
||
let mut options = OpenOptions::new(); | ||
options.write(true).create(true); | ||
|
||
#[cfg(unix)] | ||
{ | ||
use std::os::unix::fs::OpenOptionsExt; | ||
if let Some(mode) = mode { | ||
options.mode(mode); | ||
} | ||
} | ||
|
||
options | ||
.open(file_path) | ||
.map_err(|error| EnsureFileError::CreateFile { file_path: file_path.to_path_buf(), error })? | ||
.write_all(content) | ||
.map_err(|error| EnsureFileError::WriteFile { file_path: file_path.to_path_buf(), error }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
use std::io; | ||
|
||
/// Bit mask to filter executable bits (`--x--x--x`). | ||
pub const EXEC_MASK: u32 = 0b001_001_001; | ||
|
||
/// All can read and execute, but only owner can write (`rwxr-xr-x`). | ||
pub const EXEC_MODE: u32 = 0b111_101_101; | ||
|
||
/// Whether a file mode has all executable bits. | ||
pub fn is_all_exec(mode: u32) -> bool { | ||
mode & EXEC_MASK == EXEC_MASK | ||
} | ||
|
||
/// Set file mode to 777 on POSIX platforms such as Linux or macOS, | ||
/// or do nothing on Windows. | ||
#[cfg_attr(windows, allow(unused))] | ||
pub fn make_file_executable(file: &std::fs::File) -> io::Result<()> { | ||
#[cfg(unix)] | ||
return { | ||
use std::{ | ||
fs::Permissions, | ||
os::unix::fs::{MetadataExt, PermissionsExt}, | ||
}; | ||
let mode = file.metadata()?.mode(); | ||
let mode = mode | EXEC_MASK; | ||
let permissions = Permissions::from_mode(mode); | ||
file.set_permissions(permissions) | ||
}; | ||
|
||
#[cfg(windows)] | ||
return Ok(()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,109 +1,7 @@ | ||
use derive_more::{Display, Error}; | ||
use miette::Diagnostic; | ||
use std::{ | ||
fs::{self, OpenOptions}, | ||
io::{self, Write}, | ||
path::{Path, PathBuf}, | ||
}; | ||
mod ensure_file; | ||
mod symlink_dir; | ||
|
||
pub mod file_mode { | ||
/// Bit mask to filter executable bits (`--x--x--x`). | ||
pub const EXEC_MASK: u32 = 0b001_001_001; | ||
pub use ensure_file::*; | ||
pub use symlink_dir::*; | ||
|
||
/// All can read and execute, but only owner can write (`rwxr-xr-x`). | ||
pub const EXEC_MODE: u32 = 0b111_101_101; | ||
|
||
/// Whether a file mode has all executable bits. | ||
pub fn is_all_exec(mode: u32) -> bool { | ||
mode & EXEC_MASK == EXEC_MASK | ||
} | ||
} | ||
|
||
/// Create a symlink to a directory. | ||
/// | ||
/// The `link` path will be a symbolic link pointing to `original`. | ||
pub fn symlink_dir(original: &Path, link: &Path) -> io::Result<()> { | ||
#[cfg(unix)] | ||
return std::os::unix::fs::symlink(original, link); | ||
#[cfg(windows)] | ||
return junction::create(original, link); // junctions instead of symlinks because symlinks may require elevated privileges. | ||
} | ||
|
||
/// Error type of [`ensure_file`]. | ||
#[derive(Debug, Display, Error, Diagnostic)] | ||
pub enum EnsureFileError { | ||
#[display("Failed to create the parent directory at {parent_dir:?}: {error}")] | ||
CreateDir { | ||
parent_dir: PathBuf, | ||
#[error(source)] | ||
error: io::Error, | ||
}, | ||
#[display("Failed to create file at {file_path:?}: {error}")] | ||
CreateFile { | ||
file_path: PathBuf, | ||
#[error(source)] | ||
error: io::Error, | ||
}, | ||
#[display("Failed to write to file at {file_path:?}: {error}")] | ||
WriteFile { | ||
file_path: PathBuf, | ||
#[error(source)] | ||
error: io::Error, | ||
}, | ||
} | ||
|
||
/// Write `content` to `file_path` unless it already exists. | ||
/// | ||
/// Ancestor directories will be created if they don't already exist. | ||
pub fn ensure_file( | ||
file_path: &Path, | ||
content: &[u8], | ||
#[cfg_attr(windows, allow(unused))] mode: Option<u32>, | ||
) -> Result<(), EnsureFileError> { | ||
if file_path.exists() { | ||
return Ok(()); | ||
} | ||
|
||
let parent_dir = file_path.parent().unwrap(); | ||
fs::create_dir_all(parent_dir).map_err(|error| EnsureFileError::CreateDir { | ||
parent_dir: parent_dir.to_path_buf(), | ||
error, | ||
})?; | ||
|
||
let mut options = OpenOptions::new(); | ||
options.write(true).create(true); | ||
|
||
#[cfg(unix)] | ||
{ | ||
use std::os::unix::fs::OpenOptionsExt; | ||
if let Some(mode) = mode { | ||
options.mode(mode); | ||
} | ||
} | ||
|
||
options | ||
.open(file_path) | ||
.map_err(|error| EnsureFileError::CreateFile { file_path: file_path.to_path_buf(), error })? | ||
.write_all(content) | ||
.map_err(|error| EnsureFileError::WriteFile { file_path: file_path.to_path_buf(), error }) | ||
} | ||
|
||
/// Set file mode to 777 on POSIX platforms such as Linux or macOS, | ||
/// or do nothing on Windows. | ||
#[cfg_attr(windows, allow(unused))] | ||
pub fn make_file_executable(file: &std::fs::File) -> io::Result<()> { | ||
#[cfg(unix)] | ||
return { | ||
use std::{ | ||
fs::Permissions, | ||
os::unix::fs::{MetadataExt, PermissionsExt}, | ||
}; | ||
let mode = file.metadata()?.mode(); | ||
let mode = mode | file_mode::EXEC_MASK; | ||
let permissions = Permissions::from_mode(mode); | ||
file.set_permissions(permissions) | ||
}; | ||
|
||
#[cfg(windows)] | ||
return Ok(()); | ||
} | ||
pub mod file_mode; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
use std::{io, path::Path}; | ||
|
||
/// Create a symlink to a directory. | ||
/// | ||
/// The `link` path will be a symbolic link pointing to `original`. | ||
pub fn symlink_dir(original: &Path, link: &Path) -> io::Result<()> { | ||
#[cfg(unix)] | ||
return std::os::unix::fs::symlink(original, link); | ||
#[cfg(windows)] | ||
return junction::create(original, link); // junctions instead of symlinks because symlinks may require elevated privileges. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters