diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index f7c23a7f9c847..be50bfd709247 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -843,6 +843,23 @@ impl Document { impl Future> + 'static + Send, anyhow::Error, > { + #[cfg(unix)] + async fn chown(path: &Path, other: &Path) -> anyhow::Result<()> { + use std::os::unix::ffi::OsStrExt; + use std::os::unix::fs::MetadataExt; + let meta = tokio::fs::metadata(path).await?; + + // From https://github.com/uutils/coreutils/blob/2c73e978ba882c9cd56f0f16fae6f8dcce1c9850/src/uucore/src/lib/features/perms.rs#L46-L61 + let uid = meta.uid(); + let gid = meta.gid(); + let s = std::ffi::CString::new(other.as_os_str().as_bytes())?; + let ret = unsafe { libc::chown(s.as_ptr(), uid, gid) }; + if ret != 0 { + return Err(anyhow::anyhow!(tokio::io::Error::last_os_error())); + } + Ok(()) + } + log::debug!( "submitting save of doc '{:?}'", self.path().map(|path| path.to_string_lossy()) @@ -910,8 +927,11 @@ impl Document { }, ) .await??; - to_writer(&mut tmp_file, encoding_with_bom_info, &text).await?; + + let perms = tokio::fs::metadata(&path).await?.permissions(); + tmp_file.set_permissions(perms).await?; + chown(&path, &tmp_path).await?; tokio::fs::rename(tmp_path, &path).await?; let event = DocumentSavedEvent {