use crate::{Error, Result};
use std::path::Path;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum PermissionMode {
#[default]
Inherit,
ReadOnly,
Custom(u32),
}
impl PermissionMode {
pub fn apply_to_path(self, path: &Path) -> Result<()> {
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let mode = match self {
Self::Inherit => return Ok(()),
Self::ReadOnly => 0o444,
Self::Custom(m) => m,
};
let perms = std::fs::Permissions::from_mode(mode);
std::fs::set_permissions(path, perms).map_err(|e| Error::Write {
path: path.to_path_buf(),
source: e,
})?;
}
#[cfg(windows)]
{
match self {
Self::Inherit => {}
Self::ReadOnly => {
let mut perms = std::fs::metadata(path)
.map_err(|e| Error::Write {
path: path.to_path_buf(),
source: e,
})?
.permissions();
perms.set_readonly(true);
std::fs::set_permissions(path, perms).map_err(|e| Error::Write {
path: path.to_path_buf(),
source: e,
})?;
}
Self::Custom(_) => {}
}
}
Ok(())
}
#[cfg(unix)]
pub fn from_unix_mode(mode: Option<u32>) -> Option<Self> {
mode.map(Self::Custom)
}
pub fn to_unix_mode(self) -> Option<u32> {
match self {
Self::Custom(m) => Some(m),
Self::Inherit | Self::ReadOnly => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn permission_mode_default() {
assert_eq!(PermissionMode::default(), PermissionMode::Inherit);
}
#[test]
fn permission_mode_to_unix_mode() {
assert_eq!(PermissionMode::Custom(0o755).to_unix_mode(), Some(0o755));
assert_eq!(PermissionMode::Custom(0o644).to_unix_mode(), Some(0o644));
assert_eq!(PermissionMode::Inherit.to_unix_mode(), None);
assert_eq!(PermissionMode::ReadOnly.to_unix_mode(), None);
}
#[cfg(unix)]
#[test]
fn permission_mode_from_unix_mode() {
assert_eq!(
PermissionMode::from_unix_mode(Some(0o755)),
Some(PermissionMode::Custom(0o755))
);
assert_eq!(
PermissionMode::from_unix_mode(Some(0o644)),
Some(PermissionMode::Custom(0o644))
);
assert_eq!(PermissionMode::from_unix_mode(None), None);
}
}