Skip to content

Commit 219e4bd

Browse files
committed
Abstract over Path and File when setting attrs
1 parent c4313c9 commit 219e4bd

File tree

1 file changed

+65
-25
lines changed

1 file changed

+65
-25
lines changed

src/main.rs

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::{
99
collections::BTreeMap,
1010
error::Error,
1111
ffi::OsString,
12-
fs::{self, Permissions},
12+
fs::{self, File, Permissions},
1313
io::{self, Write},
1414
os::unix::{
1515
ffi::OsStrExt,
@@ -192,13 +192,13 @@ fn create(line: &Line) -> eyre::Result<()> {
192192
create_parents(file, line_type.force)?;
193193
let mut fp = fs::File::create(file).wrap_err("Creating file")?;
194194
fp.write(contents).wrap_err("Writing contents")?;
195-
if let Some(specmode) = line.mode.data.as_ref() {
196-
fp.set_permissions(Permissions::from_mode(specmode.value))
197-
.wrap_err("Setting permissions of new file")?;
198-
}
199-
let uid = line.owner.data.as_ref().map(|o| o.as_uid()).transpose()?;
200-
let gid = line.owner.data.as_ref().map(|o| o.as_gid()).transpose()?;
201-
std::os::unix::fs::fchown(&fp, uid, gid).wrap_err("Setting ownership of new file")?;
195+
set_attrs(
196+
&fp,
197+
line.mode.data.as_ref(),
198+
line.owner.data.as_ref(),
199+
line.group.data.as_ref(),
200+
"new file",
201+
)?;
202202
}
203203
config_file::LineAction::WriteFile => todo!(),
204204
config_file::LineAction::CreateAndCleanUpDirectory => {
@@ -240,12 +240,11 @@ fn create(line: &Line) -> eyre::Result<()> {
240240
}
241241
create_parents(dir, line_type.force)?;
242242
fs::DirBuilder::new().create(dir)?;
243-
fixup_attrs(
243+
set_attrs(
244244
dir,
245-
&fs::symlink_metadata(dir)?,
246-
&line.mode,
247-
&line.owner,
248-
&line.group,
245+
line.mode.data.as_ref(),
246+
line.owner.data.as_ref(),
247+
line.group.data.as_ref(),
249248
"Setting mode of new directory",
250249
)?;
251250
}
@@ -311,32 +310,73 @@ fn create(line: &Line) -> eyre::Result<()> {
311310
Ok(())
312311
}
313312

313+
// Abstraction over `File` and `Path` to use handle both in shared code
314+
trait FileRef {
315+
fn set_permissions(&self, permissions: Permissions) -> io::Result<()>;
316+
fn set_ownership(&self, uid: Option<u32>, gid: Option<u32>) -> io::Result<()>;
317+
}
318+
319+
impl FileRef for Path {
320+
fn set_permissions(&self, permissions: Permissions) -> io::Result<()> {
321+
fs::set_permissions(self, permissions)
322+
}
323+
324+
fn set_ownership(&self, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
325+
std::os::unix::fs::chown(self, uid, gid)
326+
}
327+
}
328+
329+
impl FileRef for File {
330+
fn set_permissions(&self, permissions: Permissions) -> io::Result<()> {
331+
self.set_permissions(permissions)
332+
}
333+
334+
fn set_ownership(&self, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
335+
std::os::unix::fs::fchown(self, uid, gid)
336+
}
337+
}
338+
314339
fn fixup_attrs(
315-
path: &Path,
340+
path: &(impl FileRef + ?Sized),
316341
meta: &fs::Metadata,
317342
mode: &Option<Mode>,
318343
owner: &Option<FileOwner>,
319344
group: &Option<FileOwner>,
320345
name_in_error: &str,
321346
) -> Result<(), eyre::Error> {
322-
if let Some(specmode) = mode {
323-
if specmode.value != meta.mode() {
324-
fs::set_permissions(path, Permissions::from_mode(specmode.value))
325-
.wrap_err_with(|| format!("Setting mode of {name_in_error}"))?;
326-
}
327-
}
328-
let uid = owner
347+
let mode = mode
348+
.as_ref()
349+
.filter(|specmode| specmode.value != meta.mode());
350+
let owner = owner
329351
.as_ref()
330352
.map(FileOwner::as_uid)
331353
.transpose()?
332-
.filter(|&uid| uid != meta.uid());
333-
let gid = group
354+
.filter(|&o| o != meta.uid())
355+
.map(FileOwner::Id);
356+
let group = group
334357
.as_ref()
335358
.map(FileOwner::as_gid)
336359
.transpose()?
337-
.filter(|&gid| gid != meta.gid());
360+
.filter(|&g| g != meta.gid())
361+
.map(FileOwner::Id);
362+
set_attrs(path, mode, owner.as_ref(), group.as_ref(), name_in_error)
363+
}
364+
365+
fn set_attrs(
366+
path: &(impl FileRef + ?Sized),
367+
mode: Option<&Mode>,
368+
owner: Option<&FileOwner>,
369+
group: Option<&FileOwner>,
370+
name_in_error: &str,
371+
) -> Result<(), eyre::Error> {
372+
if let Some(specmode) = mode {
373+
path.set_permissions(Permissions::from_mode(specmode.value))
374+
.wrap_err_with(|| format!("Setting mode of {name_in_error}"))?;
375+
}
376+
let uid = owner.map(FileOwner::as_uid).transpose()?;
377+
let gid = group.map(FileOwner::as_gid).transpose()?;
338378
if uid.is_some() || gid.is_some() {
339-
std::os::unix::fs::chown(path, uid, gid)
379+
path.set_ownership(uid, gid)
340380
.wrap_err_with(|| format!("Setting ownership of {name_in_error}"))?;
341381
}
342382
Ok(())

0 commit comments

Comments
 (0)