History

Extract `fstat` and `fchmod` logic to a helper

This extracts the logic that calls `fstat`, transforms the mode with `let_readers_execute`, and writes it back through the same file descriptor with `fchmod`, introducing a new helper function, `set_executable`, for it. The reason to do this is that it makes the issue of what kind of `Error` appears in the returned `Result` clearer. This may be slightly clearer to humans. It's significnatly clearer to the Rust compiler, allowing both `map_err(std::io::Error::from)` calls to be eliminated without having to write anything confusing or inelegant. (This is separate from the reason the `let_readers_execute` function, which does not access the filesystem, is its own function. That is so it's easy to test the mode transformation logic.)

Eliah Kagan committed 1 year ago

Commit fc82e781 parent de939de1 file · +12 −3Browse files

Unified · Split

gix-worktree-state/src/checkout/entry.rs+12−3
@@ -285,9 +285,7 @@ pub(crate) fn finalize_entry( · 284 unmodified lines
285285 // For possibly existing, overwritten files, we must change the file mode explicitly.
286286 #[cfg(unix)]
287287 if let Some(path) = set_executable_after_creation {
288− let old_raw_mode = rustix::fs::fstat(&file).map_err(std::io::Error::from)?.st_mode;
289− let new_mode = let_readers_execute(old_raw_mode);
290− rustix::fs::fchmod(&file, new_mode).map_err(std::io::Error::from)?;
288+ set_executable(&file)?;
291289 }
292290 // NOTE: we don't call `file.sync_all()` here knowing that some filesystems don't handle this well.
293291 // revisit this once there is a bug to fix.
@@ -296,6 +294,17 @@ pub(crate) fn finalize_entry( · 2 unmodified lines
296294 Ok(())
297295 }
298296
297+/// Use `fstat` and `fchmod` on a file descriptor to make a regular file executable.
298+///
299+/// See `let_readers_execute` for the exact details of how the mode is transformed.
300+#[cfg(unix)]
301+fn set_executable(file: &std::fs::File) -> Result<(), std::io::Error> {
302+ let old_raw_mode = rustix::fs::fstat(&file)?.st_mode;
303+ let new_mode = let_readers_execute(old_raw_mode);
304+ rustix::fs::fchmod(&file, new_mode)?;
305+ Ok(())
306+}
307+
299308 /// Given the st_mode of a regular file, compute the mode with executable bits safely added.
300309 ///
301310 /// Currently this adds executable bits for whoever has read bits already. It doesn't use the umask.