Build backend: Preserve executable bit (#10027)

Fixes #9968
This commit is contained in:
konsti 2024-12-19 17:54:44 +01:00 committed by GitHub
parent afdcea6540
commit 557e750199
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 90 additions and 8 deletions

View file

@ -596,12 +596,17 @@ impl ZipDirectoryWriter {
}
/// Add a file with the given name and return a writer for it.
fn new_writer<'slf>(&'slf mut self, path: &str) -> Result<Box<dyn Write + 'slf>, Error> {
// TODO(konsti): We need to preserve permissions, at least the executable bit.
self.writer.start_file(
path,
zip::write::FileOptions::default().compression_method(self.compression),
)?;
fn new_writer<'slf>(
&'slf mut self,
path: &str,
executable_bit: bool,
) -> Result<Box<dyn Write + 'slf>, Error> {
// 644 is the default of the zip crate.
let permissions = if executable_bit { 775 } else { 664 };
let options = zip::write::FileOptions::default()
.unix_permissions(permissions)
.compression_method(self.compression);
self.writer.start_file(path, options)?;
Ok(Box::new(&mut self.writer))
}
}
@ -626,7 +631,16 @@ impl DirectoryWriter for ZipDirectoryWriter {
fn write_file(&mut self, path: &str, file: &Path) -> Result<(), Error> {
trace!("Adding {} from {}", path, file.user_display());
let mut reader = BufReader::new(File::open(file)?);
let mut writer = self.new_writer(path)?;
// Preserve the executable bit, especially for scripts
#[cfg(unix)]
let executable_bit = {
use std::os::unix::fs::PermissionsExt;
file.metadata()?.permissions().mode() & 0o111 != 0
};
// Windows has no executable bit
#[cfg(not(unix))]
let executable_bit = false;
let mut writer = self.new_writer(path, executable_bit)?;
let record = write_hashed(path, &mut reader, &mut writer)?;
drop(writer);
self.record.push(record);
@ -644,7 +658,11 @@ impl DirectoryWriter for ZipDirectoryWriter {
let record_path = format!("{dist_info_dir}/RECORD");
trace!("Adding {record_path}");
let record = mem::take(&mut self.record);
write_record(&mut self.new_writer(&record_path)?, dist_info_dir, record)?;
write_record(
&mut self.new_writer(&record_path, false)?,
dist_info_dir,
record,
)?;
trace!("Adding central directory");
self.writer.finish()?;