Skip to content

Commit 0ea2744

Browse files
ardurinPr0methean
andauthored
Add function to raw copy files and update metadata (#260)
Co-authored-by: Chris Hennick <4961925+Pr0methean@users.noreply.github.com>
1 parent a5722e6 commit 0ea2744

File tree

1 file changed

+50
-5
lines changed

1 file changed

+50
-5
lines changed

src/write.rs

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,11 +1258,7 @@ impl<W: Write + Seek> ZipWriter<W> {
12581258
/// Ok(())
12591259
/// }
12601260
/// ```
1261-
pub fn raw_copy_file_rename<S: ToString>(
1262-
&mut self,
1263-
mut file: ZipFile,
1264-
name: S,
1265-
) -> ZipResult<()> {
1261+
pub fn raw_copy_file_rename<S: ToString>(&mut self, file: ZipFile, name: S) -> ZipResult<()> {
12661262
let mut options = SimpleFileOptions::default()
12671263
.large_file(file.compressed_size().max(file.size()) > spec::ZIP64_BYTES_THR)
12681264
.last_modified_time(
@@ -1274,7 +1270,15 @@ impl<W: Write + Seek> ZipWriter<W> {
12741270
options = options.unix_permissions(perms);
12751271
}
12761272
Self::normalize_options(&mut options);
1273+
self.raw_copy_file_rename_internal(file, name, options)
1274+
}
12771275

1276+
fn raw_copy_file_rename_internal<S: ToString>(
1277+
&mut self,
1278+
mut file: ZipFile,
1279+
name: S,
1280+
options: SimpleFileOptions,
1281+
) -> ZipResult<()> {
12781282
let raw_values = ZipRawValues {
12791283
crc32: file.crc32(),
12801284
compressed_size: file.compressed_size(),
@@ -1330,6 +1334,47 @@ impl<W: Write + Seek> ZipWriter<W> {
13301334
self.raw_copy_file_rename(file, name)
13311335
}
13321336

1337+
/// Add a new file using the already compressed data from a ZIP file being read and set the last
1338+
/// modified date and unix mode. This allows faster copies of the `ZipFile` since there is no need
1339+
/// to decompress and compress it again. Any `ZipFile` metadata other than the last modified date
1340+
/// and the unix mode is copied and not checked, for example the file CRC.
1341+
///
1342+
/// ```no_run
1343+
/// use std::io::{Read, Seek, Write};
1344+
/// use zip::{DateTime, ZipArchive, ZipWriter};
1345+
///
1346+
/// fn copy<R, W>(src: &mut ZipArchive<R>, dst: &mut ZipWriter<W>) -> zip::result::ZipResult<()>
1347+
/// where
1348+
/// R: Read + Seek,
1349+
/// W: Write + Seek,
1350+
/// {
1351+
/// // Retrieve file entry by name
1352+
/// let file = src.by_name("src_file.txt")?;
1353+
///
1354+
/// // Copy the previously obtained file entry to the destination zip archive
1355+
/// dst.raw_copy_file_touch(file, DateTime::default(), Some(0o644))?;
1356+
///
1357+
/// Ok(())
1358+
/// }
1359+
/// ```
1360+
pub fn raw_copy_file_touch(
1361+
&mut self,
1362+
file: ZipFile,
1363+
last_modified_time: DateTime,
1364+
unix_mode: Option<u32>,
1365+
) -> ZipResult<()> {
1366+
let name = file.name().to_owned();
1367+
let mut options = SimpleFileOptions::default()
1368+
.large_file(file.compressed_size().max(file.size()) > spec::ZIP64_BYTES_THR)
1369+
.last_modified_time(last_modified_time)
1370+
.compression_method(file.compression());
1371+
if let Some(perms) = unix_mode {
1372+
options = options.unix_permissions(perms);
1373+
}
1374+
Self::normalize_options(&mut options);
1375+
self.raw_copy_file_rename_internal(file, name, options)
1376+
}
1377+
13331378
/// Add a directory entry.
13341379
///
13351380
/// As directories have no content, you must not call [`ZipWriter::write`] before adding a new file.

0 commit comments

Comments
 (0)